Common problems

From ClassDBI

Jump to: navigation, search

Common Problems

Contents

Create doesn't actually

Symptom:

Create doesn't actually insert the new record in the database. Probable Cause: You are in transaction mode.

Solution:

1) Commit your change when you're done:

 my $object = Class->create(\%data);
 Class->dbi_commit;

2) Set autocommit in your database connection:

 __PACKAGE__->set_db(Main => $dsn, $user, $pass, {AutoCommit=>1});

"X is not a column of" for many-to-many

Symptom: You have a one-to-many relationship defined in your custom CDBI class and receive the following error when trying to use your database:

 test is not a column of MyDBI::Test2 at <some line in 
 Class/DBI/Relationship/HasMany.pm>

Solution: In the example above, 'test' is not a column name--it's the value of the linked column. This looks like a bug in CDBI until you stumble upon the following important note in the documentation:

(Note that because this happens at compile time, if the foreign class is defined in the same file, the class with the has_a() must be defined earlier than the class with the has_many(). If the classes are in different files, Class::DBI should be able to do the right thing)

Failed updates with no errors

Symptom: Updates to a record are not working and no errors are being returned.

Solution: You may be trying to update the primary key. As documented (as of v0.96), it is not possible to update the primary key and any attempts will silently fail.

Other possible reasons:

2) You're forgetting to call the update() method after you change the value via its mutator.

3) You're correctly calling update(), but you're using Oracle or PostgreSQL (both of which default to AutoCommit off) or have set AutoCommit to be off in some other fashion, and you're forgetting to call dbi_commit().

4) You're correctly calling update() and dbi_commit(), but you overrode the db_Main() method and forgot to call __PACKAGE__->_remember_handle('Main') so that dbi_commit() will actually work.

Old data due to object index

Symptom: After updating a record, the changes do not appear in subsequent retrievals or mystery records that you thought were deleted show up again (aka, Debugging the Object Index).

Solution: It's likely that the record you updated is being kept in the object index due to a variable scoping problem or unintentional closure. See the POD about Uniqueness of Objects in Memory. A few debugging hints:

  • Try removing the object from the index before updating or deleting it:
    $record->remove_from_object_index
  • Try clearing the index:
    $record->clear_object_index;
  • If either of these solutions work, then you should try to find the variable which is holding the record. It could be a global variable in a persistent environment (e.g. mod_perl) or an accidental closure.
  • You can dump the object index by adding the following line to Class/DBI.pm:
    sub get_index { return \%Live_Objects };

Then in your code add:

    warn Dumper(MyDBI->get_index);
  • If none of these solutions work or you are in a rush, you may want to try globally disabling the object index by adding the following line to your top-most Class::DBI subclass:
    $Class::DBI::Weaken_Is_Available = 0;

Old data due to non-uniqueness of objects in memory

Symptom: After updating a record, other copies of the object do not reflect the changes, apparently violating "Uniqueness of objects in memory".

Solution: There is a long thread about this problem on the CDBI list: [1]

Here are some of the possible causes, suggested in the thread:

1. Objects stored in a (serialized) session object are typically unavailable to CDBI's object index. Upshot: Don't store objects there -- only store scalars (object ID's, etc.) The object index works by keeping a hash of weak references to all objects in the current process as they are loaded from the database. It does this in the constructor. Things you put in the session are never loaded from the database again, so they don't get registered in the object index. The session just runs the object through a Storable::thaw, without calling the constructor.

2. You are using an older Class::DBI that doesn't support this feature

3. Your Perl doesn't support weak references. Check the docs for more info.

4. Your primary key for this class is defined incorrectly, so these objects do not appear the same to Class::DBI.

5. Browser is caching the page.

6. Side effect of Template Toolkit stash cloning


"Can't retrieve a reference"

Symptom:

Retrieve returns "Can't retrieve a reference" because no matter how hard I try to force my CDBI object into scalar context it is always treated as a (blessed) reference.

So far I have only got this to work (with CDBI v0.96):

  $col_name = $ob->primary_column->name;

or

  $col_name = $ob->find_column('column_name')->name();
  $scalar_val = $ob->$col_name;

Solution:

This will force the CDBI object into scalar context and give you the column value:

 $class->retrieve("$ob");


Note: This will only work as expected if you haven't set your own stringify/to_string method for the given class. You may well be better off doing $class->retrieve($ob->id).

"You have an error in your SQL syntax."

Symptom:

DBD::mysql::st execute failed: You have an error in your SQL syntax.

Solution:

Make sure you're not using MySQL's reserved words. The words can be found at [2]. There could be other problems causing this error, but this is a common one.

Personal tools