[Dbix-class] Pg patch from konobi - can people test please?

Jesper Krogh jesper at krogh.cc
Thu Apr 27 16:45:54 CEST 2006


Hi.

The patch is probably correct (copied from the Rails-counterpart), but this
functionality is in Perl coded directly in DBD::Pg.

I still think that it's migrating code from DBD::Pg that shouldn't be
there. There is a bug in the code, but thats fixed by this (much simpler)
patch.

The bug is that the sequence-lookup does not supply the fully qualified
sequence so when the table is not in the search_path it fails to get the
"insert_id" from the sequence.


Index: t/run/12pg.tl
===================================================================
--- t/run/12pg.tl       (revision 1522)
+++ t/run/12pg.tl       (working copy)
@@ -50,7 +50,7 @@
 my $type_info = PgTest->schema->storage->columns_info_for('artist');
 my $artistid_defval = delete $type_info->{artistid}->{default_value};
 like($artistid_defval,
-     qr/^nextval\('public\.artist_artistid_seq'::(?:text|regclass)\)/,
+    
qr/^nextval\('([^\.]*\.){0,1}artist_artistid_seq'::(?:text|regclass)\)/,
      'columns_info_for - sequence matches Pg get_autoinc_seq expectations');
 is_deeply($type_info, $test_type_info,
           'columns_info_for - column data types');
Index: lib/DBIx/Class/Storage/DBI/Pg.pm
===================================================================
--- lib/DBIx/Class/Storage/DBI/Pg.pm    (revision 1522)
+++ lib/DBIx/Class/Storage/DBI/Pg.pm    (working copy)
@@ -21,11 +21,11 @@
   my ($schema,$table) = $source->name =~ /^(.+)\.(.+)$/ ? ($1,$2)
     : (undef,$source->name);
   while (my $col = shift @pri) {
-    my $info =
$dbh->column_info(undef,$schema,$table,$col)->fetchrow_arrayref;
-    if (defined $info->[12] and $info->[12] =~
+    my $info =
$dbh->column_info(undef,$schema,$table,$col)->fetchrow_hashref;
+    if (defined $info->{COLUMN_DEF} and $info->{COLUMN_DEF} =~
       /^nextval\(+'([^']+)'::(?:text|regclass)\)/)
     {
-      return $1; # may need to strip quotes -- see if this works
+      return $info->{TABLE_SCHEM} . "." . $1; # may need to strip quotes
-- see if this works
     }
   }
 }


This is sample output fom the $info;

#           'DECIMAL_DIGITS' => undef,
#          'COLUMN_DEF' => 'nextval(\'other4.testtable_id_seq\'::regclass)',
#          'TABLE_CAT' => undef,
#          'NUM_PREC_RADIX' => undef,
#          'TABLE_SCHEM' => 'other4',
#          'BUFFER_LENGTH' => undef,
#          'CHAR_OCTET_LENGTH' => undef,
#          'pg_constraint' => undef,
#          'IS_NULLABLE' => 'NO',
#          'REMARKS' => undef,
#          'COLUMN_SIZE' => 4,
#          'ORDINAL_POSITION' => '1',
#          'COLUMN_NAME' => 'id',
#          'TYPE_NAME' => 'integer',
#          'pg_type' => 'integer',
#          'NULLABLE' => '0',
#          'DATA_TYPE' => 4,
#          'TABLE_NAME' => 'testtable',
#          'SQL_DATA_TYPE' => undef,
#          'SQL_DATETIME_SUB' => undef


> konobi's lobbed together a patch for Storage::DBI::Pg that hopefully
> improves sequence etc. support - can people who know/use such things more
> than I have a look over and say whether it's suitable for inclusion?
>
> === Pg.pm
> ==================================================================
> --- Pg.pm       (revision 1247)
> +++ Pg.pm       (local)
> @@ -20,14 +20,50 @@
> my $dbh = $self->_dbh; my ($schema,$table) = $source->name =~
> /^(.+)\.(.+)$/ ? ($1,$2)
> : (undef,$source->name);
> -  while (my $col = shift @pri) {
> -    my $info =
> $dbh->column_info(undef,$schema,$table,$col)->fetchrow_arrayref;
> -    if (defined $info->[12] and $info->[12] =~
> -      /^nextval\(+'([^']+)'::(?:text|regclass)\)/)
> -    {
> -      return $1; # may need to strip quotes -- see if this works
> -    }
> +
> +  # First try looking for a sequence with a dependency on the
> +  # given table's primary key.
> +  my $sql = qq{
> +    SELECT attr.attname, name.nspname, seq.relname
> +    FROM pg_class      seq,
> +         pg_attribute  attr,
> +         pg_depend     dep,
> +         pg_namespace  name,
> +         pg_constraint cons
> +    WHERE seq.oid           = dep.objid
> +      AND seq.relnamespace  = name.oid
> +      AND seq.relkind       = 'S'
> +      AND attr.attrelid     = dep.refobjid
> +      AND attr.attnum       = dep.refobjsubid
> +      AND attr.attrelid     = cons.conrelid
> +      AND attr.attnum       = cons.conkey[1]
> +      AND cons.contype      = 'p'
> +      AND dep.refobjid      = '$table'::regclass
> +  };
> +  my %hash_details;
> +  @hash_details{qw(name namespace seqname)} =
> $dbh->selectrow_array($sql);
> +
> +  if( !scalar(values(%hash_details)) ){
> +    # If that fails, try parsing the primary key's default value.
> +    # Support the 7.x and 8.0 nextval('foo'::text) as well as
> +    # the 8.1+ nextval('foo'::regclass).
> +    # TODO: assumes sequence is in same schema as table.
> +    my $sql2 = qq{
> +        SELECT attr.attname, name.nspname, split_part(def.adsrc, '\\\'',
> 2)
> +        FROM pg_class       t
> +        JOIN pg_namespace   name ON (t.relnamespace = name.oid)
> +        JOIN pg_attribute   attr ON (t.oid = attrelid)
> +        JOIN pg_attrdef     def  ON (adrelid = attrelid AND adnum =
> attnum) +        JOIN pg_constraint  cons ON (conrelid = adrelid AND adnum
> = conkey[1])
> +        WHERE t.oid = '$table'::regclass
> +        AND cons.contype = 'p'
> +        AND def.adsrc ~* 'nextval'
> +    };
> +    @hash_details{qw(name namespace seqname)} =
> $dbh->selectrow_array($sql2);
>
>
> }
> +
> +  # check for existence of . in sequence name as in public.foo_sequence.
> if it does not exist, join the current namespace +  return
> $hash_details{seqname} =~ m{\.} ? $hash_details{seqname} :
> $hash_details{namespace} .q{.}. $hash_details{seqname};
> }
>
>
> sub sqlt_type {
>
> --
> Matt S Trout       Offering custom development, consultancy and support
> Technical Director    contracts for Catalyst, DBIx::Class and BAST.
> Contact
> Shadowcat Systems Ltd.  mst (at) shadowcatsystems.co.uk for more
> information
>
> + Help us build a better perl ORM:
> http://dbix-class.shadowcatsystems.co.uk/ +
>
>
> _______________________________________________
> List: http://lists.rawmode.org/cgi-bin/mailman/listinfo/dbix-class
> Wiki: http://dbix-class.shadowcatsystems.co.uk/
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/
>
>


-- 
Jesper Krogh




More information about the Dbix-class mailing list