=cut
+# override this in a subclass if your DBD ->can('column_info'),
+# but the call itself is horribly broken.
+sub _column_info_broken { 0 }
+
sub columns_info_for {
my ($self, $table) = @_;
+
my %result;
- if ( $self->dbh->can( 'column_info' ) ){
+ if ( $self->dbh->can( 'column_info' ) && !$self->_column_info_broken){
my $sth = $self->dbh->column_info( undef, undef, $table, '%' );
$sth->execute();
while ( my $info = $sth->fetchrow_hashref() ){
my %column_info;
$column_info{data_type} = $info->{TYPE_NAME};
$column_info{size} = $info->{COLUMN_SIZE};
- $column_info{is_nullable} = $info->{NULLABLE};
+ $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0;
+ $column_info{default_value} = $info->{COLUMN_DEF};
$result{$info->{COLUMN_NAME}} = \%column_info;
}
} else {
my $sth = $self->dbh->prepare("SELECT * FROM $table WHERE 1=0");
$sth->execute;
- my @columns = @{$sth->{NAME}};
+ my @columns = @{$sth->{NAME_lc}};
for my $i ( 0 .. $#columns ){
- $result{$columns[$i]}{data_type} = $sth->{TYPE}->[$i];
+ my %column_info;
+ my $type_num = $sth->{TYPE}->[$i];
+ my $type_name;
+ if(defined $type_num && $self->dbh->can('type_info')) {
+ my $type_info = $self->dbh->type_info($type_num);
+ $type_name = $type_info->{TYPE_NAME} if $type_info;
+ }
+ $column_info{data_type} = $type_name ? $type_name : $type_num;
+ $column_info{size} = $sth->{PRECISION}->[$i];
+ $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0;
+ $result{$columns[$i]} = \%column_info;
}
}
return \%result;
# __PACKAGE__->load_components(qw/PK::Auto/);
+sub _column_info_broken { 1 }
+
sub last_insert_id
{
my ($self) = @_;
my $type_info = $schema->storage->columns_info_for('artist');
my $test_type_info = {
'artistid' => {
- 'data_type' => 'INTEGER'
+ 'data_type' => 'INTEGER',
+ 'is_nullable' => 0,
+ 'size' => undef,
},
'name' => {
- 'data_type' => 'varchar'
+ 'data_type' => 'varchar',
+ 'is_nullable' => 0,
+ 'size' => undef,
}
};
is_deeply($type_info, $test_type_info, 'columns_info_for - column data types');
'artistid' => {
'data_type' => 'INT',
'is_nullable' => 0,
- 'size' => 11
+ 'size' => 11,
+ 'default_value' => undef,
},
'name' => {
'data_type' => 'VARCHAR',
'is_nullable' => 1,
- 'size' => 255
+ 'size' => 255,
+ 'default_value' => undef,
},
'charfield' => {
'data_type' => 'VARCHAR',
'is_nullable' => 1,
- 'size' => 10
+ 'size' => 10,
+ 'default_value' => undef,
},
};
plan skip_all, 'Set $ENV{DBICTEST_PG_DSN}, _USER and _PASS to run this test'
. ' (note: creates and drops a table named artist!)' unless ($dsn && $user);
-plan tests => 3;
+plan tests => 4;
DBICTest::Schema->compose_connection('PgTest' => $dsn, $user, $pass);
'artistid' => {
'data_type' => 'integer',
'is_nullable' => 0,
- 'size' => 4
+ 'size' => 4,
},
'name' => {
'data_type' => 'character varying',
'is_nullable' => 1,
- 'size' => 255
+ 'size' => 255,
+ 'default_value' => undef,
},
'charfield' => {
'data_type' => 'character',
'is_nullable' => 1,
- 'size' => 10
+ 'size' => 10,
+ 'default_value' => undef,
},
};
+
my $type_info = PgTest->schema->storage->columns_info_for('artist');
-is_deeply($type_info, $test_type_info, 'columns_info_for - column data types');
+my $artistid_defval = delete $type_info->{artistid}->{default_value};
+like($artistid_defval,
+ qr/^nextval\('public\.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');
$dbh->do("DROP TABLE artist;");
plan skip_all, 'Set $ENV{DBICTEST_DB2_DSN}, _USER and _PASS to run this test'
unless ($dsn && $user);
-plan tests => 5;
+plan tests => 6;
DBICTest::Schema->compose_connection('DB2Test' => $dsn, $user, $pass);
my $dbh = DB2Test->schema->storage->dbh;
-$dbh->do("DROP TABLE artist;");
+{
+ local $SIG{__WARN__} = sub {};
+ $dbh->do("DROP TABLE artist;");
+}
$dbh->do("CREATE TABLE artist (artistid INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), name VARCHAR(255), charfield CHAR(10));");
}
);
is( $it->count, 3, "LIMIT count ok" );
-is( $it->next->name, "Artist 2", "iterator->next ok" );
-$it->next;
+is( $it->next->name, "foo", "iterator->next ok" );
$it->next;
+is( $it->next->name, "Artist 2", "iterator->next ok" );
is( $it->next, undef, "next past end of resultset ok" );
my $test_type_info = {
'artistid' => {
'data_type' => 'INTEGER',
'is_nullable' => 0,
- 'size' => 11
+ 'size' => 10
},
'name' => {
'data_type' => 'VARCHAR',
'size' => 255
},
'charfield' => {
- 'data_type' => 'VARCHAR',
+ 'data_type' => 'CHAR',
'is_nullable' => 1,
'size' => 10
},