create failures with has_one

7 messages Options
Embed this post
Permalink
Dermot

create failures with has_one

Reply Threaded More More options
Print post
Permalink
Hi,

I have had a number of errors trying to add a record to a SQLite3 db
and DBIx  '0.08010';
The original error was:

DBIx::Class::ResultSet::update_or_create(): Object ARRAY(0x8f3f7a8)
isn't a My::Schema::MotionDB::

I created a small test to see if I could narrow it down but that is
throwing this exception:

DBIx::Class::ResultSet::update_or_create(): DBI Exception:
DBD::SQLite::db prepare_cached failed: near "CONTRIB": syntax error(1)
at dbdimp.c line 271 [for Statement "SELECT me.id, me.sub_id,
me.contrib_id FROM clipData me WHERE ( ( ( ( me.id CONTRIB ID ? ) ) )
)"] at t/test_update_or_create.t line 45

I can't find 'CONTRIB ID' anywhere on my sources. I have parred my
schema and script down to the bone but as long as I try and create a
row with a row in a related (has_one) table, I get errors.

Can anyone spot where I am going wrong?
TIA,
Dp.



#!/usr/local/bin/perl

use strict;
use warnings;
use FindBin qw($Bin);
use Path::Class;
use lib dir ($Bin,'..','lib')->stringify;
use My::Schema::MotionDB;
use Config::General;
use Data::Dumper;

my $debug = 1;

my $path = $Bin.'..';
my @configPath = ($path, $Bin);
my $config = new Config::General(-ConfigFile => 'motion.conf',
-ConfigPath=> \@configPath, -BackslashEscape => 1);
my %config = $config->getall;

my $HOME = dir($Bin, '..');
my $dsn = $config{'Model::MotionDB'}{'connect_info'}[0];

$dsn =~ s/__HOME__/$HOME/;
print "DSN=$dsn CONF=$config{'Model::MotionDB'}{'connect_info'}[0]\n"
if $debug == 1;

my $schema = My::Schema::MotionDB->connect($dsn) ||
        die "Failed fo connect to the database at $dsn $!\n";

my $record = {
          'validation_pass' => 1,
          'files' => [],
          'active' => 1,
          'name' => 'Gustav MR',
          'clipdata' => [
                          {
                            'contrib_id' => 2,
                          }
                        ],
          'contrib_id' => 2,
        };

print Dumper ($record);
my $row = $schema->resultset('Submissions')->update_or_create($record,
{key => 'name_unique'});
print STDERR "Adding record\n" if $debug == 1;


==============
package My::Schema::MotionDB::Submissions;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("submissions");
__PACKAGE__->add_columns(
  "id",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
  "name",
  { data_type => "VARCHAR", is_nullable => 0, size => 10 },
  "contrib_id",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
  "active",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
  "validation_pass",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("name_unique", ["name"]);
__PACKAGE__->belongs_to(
                contrib_id => 'My::Schema::MotionDB::Contributors',
                );
__PACKAGE__->has_one(
                clipdata => 'My::Schema::MotionDB::Clipdata', 'sub_id'
                );
__PACKAGE__->has_many(
                files => 'My::Schema::MotionDB::Files', 'sub_id'

1;

package My::Schema::MotionDB::Clipdata;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("clipData");
__PACKAGE__->add_columns(
  "id",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
  "sub_id",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
  "contrib_id",
  { data_type => "INTEGER", is_nullable => 0, size => undef },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint(
        unique_sub => [ qw/sub_id/]
         );
__PACKAGE__->belongs_to(
                        submission =>
'My::Schema::MotionDB::Submissions', 'sub_id');

__PACKAGE__->belongs_to(
                        contributor =>
'My::Schema::MotionDB::Contributors', 'contrib_id');
1;

================================

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Wallace Reis-2

Re: create failures with has_one

Reply Threaded More More options
Print post
Permalink
On 14/10/2009, at 13:10, Dermot wrote:

> DBIx::Class::ResultSet::update_or_create(): Object ARRAY(0x8f3f7a8)
> isn't a My::Schema::MotionDB::
>
> I created a small test to see if I could narrow it down but that is
> throwing this exception:
>
> DBIx::Class::ResultSet::update_or_create(): DBI Exception:
> DBD::SQLite::db prepare_cached failed: near "CONTRIB": syntax error(1)
> at dbdimp.c line 271 [for Statement "SELECT me.id, me.sub_id,
> me.contrib_id FROM clipData me WHERE ( ( ( ( me.id CONTRIB ID ? ) ) )
> )"] at t/test_update_or_create.t line 45
>
> my $record = {
>         'validation_pass' => 1,
>         'files' => [],
>         'active' => 1,
>         'name' => 'Gustav MR',
>         'clipdata' => [
>                         {
>                           'contrib_id' => 2,
>                         }
>                       ],
>         'contrib_id' => 2,
>       };
>

Use a HashRef for clipdata rel instead of a ArrayRef.

--
   wallace reis/wreis         Catalyst and DBIx::Class consultancy  
with a clue
   Software Engineer          and a commit bit: http://shadowcat.co.uk/catalyst/
Shadowcat Systems Limited
http://www.shadowcat.co.uk     http://www.linkedin.com/in/wallacereis

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Wallace Reis-2

Re: create failures with has_one

Reply Threaded More More options
Print post
Permalink
On 15/10/2009, at 08:34, Dermot wrote:

> 2009/10/15 Wallace Reis <[hidden email]>:
>> On 14/10/2009, at 13:10, Dermot wrote:
>>>
>>> my $record = {
>>>         'validation_pass' => 1,
>>>         'files' => [],
>>>         'active' => 1,
>>>         'name' => 'Gustav MR',
>>>         'clipdata' => [
>>>                         {
>>>                           'contrib_id' => 2,
>>>                         }
>>>                       ],
>>>         'contrib_id' => 2,
>>>       };
>>>
>>
>> Use a HashRef for clipdata rel instead of a ArrayRef.
>
> Thanx for the replay.
>
> Under ~/Class/ResultSet.pm#create it says use a Arrayref for has_one
>
> "Example of creating a new row and also creating rows in a related
> has_many or has_one resultset. Note Arrayref."

Patches are welcome!

> I think my problem was using update_or_create(). I think there are
> differences between the what create() and what update_or_create()
> expects. This might explain the Recursive update error I got as well.
>
> At the moment I am using find_or_create() and that is working as  
> expected.


There is no difference between those APIs, both update_or_create and  
find_or_create use ->create.

--
    wallace reis/wreis         Catalyst and DBIx::Class consultancy  
with a clue
    Software Engineer          and a commit bit: http://shadowcat.co.uk/catalyst/
Shadowcat Systems Limited
http://www.shadowcat.co.uk     http://www.linkedin.com/in/wallacereis

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Peter Rabbitson-2

Re: create failures with has_one

Reply Threaded More More options
Print post
Permalink
In reply to this post by Dermot
On Wed, Oct 14, 2009 at 05:10:57PM +0100, Dermot wrote:

> Hi,
>
> I have had a number of errors trying to add a record to a SQLite3 db
> and DBIx  '0.08010';
> The original error was:
>
> DBIx::Class::ResultSet::update_or_create(): Object ARRAY(0x8f3f7a8)
> isn't a My::Schema::MotionDB::
>
> I created a small test to see if I could narrow it down but that is
> throwing this exception:
>
> DBIx::Class::ResultSet::update_or_create(): DBI Exception:
> DBD::SQLite::db prepare_cached failed: near "CONTRIB": syntax error(1)
> at dbdimp.c line 271 [for Statement "SELECT me.id, me.sub_id,
> me.contrib_id FROM clipData me WHERE ( ( ( ( me.id CONTRIB ID ? ) ) )
> )"] at t/test_update_or_create.t line 45
>
> I can't find 'CONTRIB ID' anywhere on my sources. I have parred my
> schema and script down to the bone but as long as I try and create a
> row with a row in a related (has_one) table, I get errors.
>
> Can anyone spot where I am going wrong?

Yes, you are using a version that is almost 2 years old. Upgrade
to the 0.081xx family which sports a from the ground rewrite of
multicreate (among other things).

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Wallace Reis-2

Re: create failures with has_one

Reply Threaded More More options
Print post
Permalink
In reply to this post by Wallace Reis-2
On 15/10/2009, at 21:08, Dermot wrote:

> 2009/10/15 Wallace Reis <[hidden email]>:
>> On 15/10/2009, at 08:34, Dermot wrote:
>>
>>> 2009/10/15 Wallace Reis <[hidden email]>:
>>>>
>>>> On 14/10/2009, at 13:10, Dermot wrote:
>>>>>
>>>>> my $record = {
>>>>>        'validation_pass' => 1,
>>>>>        'files' => [],
>>>>>        'active' => 1,
>>>>>        'name' => 'Gustav MR',
>>>>>        'clipdata' => [
>>>>>                        {
>>>>>                          'contrib_id' => 2,
>>>>>                        }
>>>>>                      ],
>>>>>        'contrib_id' => 2,
>>>>>      };
>>>>>
>>>>
>>>> Use a HashRef for clipdata rel instead of a ArrayRef.

Here, you should note that currently find (and update) part of  
*_or_create methods will fail for nested relations, so you need to  
call find(update)_or_create for relationships separately.

> I would really, really love to do a doc patch if I knew how. Mostly
> because that's all I feel I have the ability to do. However I have no
> experience of how to create patches. I guess it's a similar to `svn
> diff > ...`. Is there something on the Advent Calendar's or similar
> that might show me?

Not sure, but a "svn diff" output or a "svk ci -P" patch is fine.

--
    wallace reis/wreis         Catalyst and DBIx::Class consultancy  
with a clue
    Software Engineer          and a commit bit: http://shadowcat.co.uk/catalyst/
Shadowcat Systems Limited
http://www.shadowcat.co.uk     http://www.linkedin.com/in/wallacereis

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Dermot

Re: create failures with has_one

Reply Threaded More More options
Print post
Permalink
2009/10/19 Wallace Reis <[hidden email]>:

> On 15/10/2009, at 21:08, Dermot wrote:
>>>>>> my $record = {
>>>>>>       'validation_pass' => 1,
>>>>>>       'files' => [],
>>>>>>       'active' => 1,
>>>>>>       'name' => 'Gustav MR',
>>>>>>       'clipdata' => [
>>>>>>                       {
>>>>>>                         'contrib_id' => 2,
>>>>>>                       }
>>>>>>                     ],
>>>>>>       'contrib_id' => 2,
>>>>>>     };
>>>>>>
>>>>>
>>>>> Use a HashRef for clipdata rel instead of a ArrayRef.
>
> Here, you should note that currently find (and update) part of *_or_create
> methods will fail for nested relations, so you need to call
> find(update)_or_create for relationships separately.

That might explain why, even under 0.08112, I get
"DBIx::Class::ResultSet::find_or_create(): new_result needs a hash..."
when I use a nested structure. Are there any methods I can use that
will allow me to create new, nested rows?


>> I would really, really love to do a doc patch if I knew how. Mostly
>> because that's all I feel I have the ability to do. However I have no
>> experience of how to create patches. I guess it's a similar to `svn
>> diff > ...`. Is there something on the Advent Calendar's or similar
>> that might show me?
>
> Not sure, but a "svn diff" output or a "svk ci -P" patch is fine.


Thanx for this tip. I'd better get my facts right before I submit.
Dp.

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...
Wallace Reis-2

Re: create failures with has_one

Reply Threaded More More options
Print post
Permalink
On 19/10/2009, at 11:59, Dermot wrote:

> 2009/10/19 Wallace Reis <[hidden email]>:
>> On 15/10/2009, at 21:08, Dermot wrote:
>>>>>>> my $record = {
>>>>>>>       'validation_pass' => 1,
>>>>>>>       'files' => [],
>>>>>>>       'active' => 1,
>>>>>>>       'name' => 'Gustav MR',
>>>>>>>       'clipdata' => [
>>>>>>>                       {
>>>>>>>                         'contrib_id' => 2,
>>>>>>>                       }
>>>>>>>                     ],
>>>>>>>       'contrib_id' => 2,
>>>>>>>     };
>>>>>>>
>>>>>>
>>>>>> Use a HashRef for clipdata rel instead of a ArrayRef.
>
> That might explain why, even under 0.08112, I get
> "DBIx::Class::ResultSet::find_or_create(): new_result needs a hash..."
> when I use a nested structure. Are there any methods I can use that
> will allow me to create new, nested rows?

You can encapsulate it in a resultset method like:

sub import_record {
     my ( $self, $record ) = @_;
     my ( $files, $clipdata ) = map { delete $record->{$_} } qw/files  
clipdata/;
     my $schema = $self->result_source->schema;

     my $imp_rec;
     my $import_txn = sub {
         my $imported_record = $self->update_or_create($record);
         foreach my $file (@$files) {
             $imported_record->update_or_create_related('files', $file,
                 { key => 'files_filename' }
             );
         }
         $imported_record->update_or_create_related('clipdata',  
$clipdata);
         return $imported_record;
     };
     eval { $imp_rec = $schema->txn_do($import_txn) };
     if ($@) {                                      # Transaction failed
         die "something terrible has happened!"     #
             if ($@ =~ /Rollback failed/);          # Rollback failed

         # deal_with_failed_transaction();
     }
     return $imp_rec;
}

then call $schema->resultset('Submissions')->import_record($record).

--
    wallace reis/wreis         Catalyst and DBIx::Class consultancy  
with a clue
    Software Engineer          and a commit bit: http://shadowcat.co.uk/catalyst/
Shadowcat Systems Limited
http://www.shadowcat.co.uk     http://www.linkedin.com/in/wallacereis

_______________________________________________
List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
Searchable Archive: http://www.grokbase.com/group/dbix-class@...