1package DBIx::Class::Schema::Loader::DBI::Pg; 2 3use strict; 4use warnings; 5use base qw/ 6 DBIx::Class::Schema::Loader::DBI::Component::QuotedDefault 7 DBIx::Class::Schema::Loader::DBI 8/; 9use Carp::Clan qw/^DBIx::Class/; 10use Class::C3; 11 12our $VERSION = '0.05003'; 13 14=head1 NAME 15 16DBIx::Class::Schema::Loader::DBI::Pg - DBIx::Class::Schema::Loader::DBI 17PostgreSQL Implementation. 18 19=head1 SYNOPSIS 20 21 package My::Schema; 22 use base qw/DBIx::Class::Schema::Loader/; 23 24 __PACKAGE__->loader_options( debug => 1 ); 25 26 1; 27 28=head1 DESCRIPTION 29 30See L<DBIx::Class::Schema::Loader::Base>. 31 32=cut 33 34sub _setup { 35 my $self = shift; 36 37 $self->next::method(@_); 38 $self->{db_schema} ||= 'public'; 39} 40 41 42sub _table_uniq_info { 43 my ($self, $table) = @_; 44 45 # Use the default support if available 46 return $self->next::method($table) 47 if $DBD::Pg::VERSION >= 1.50; 48 49 my @uniqs; 50 my $dbh = $self->schema->storage->dbh; 51 52 # Most of the SQL here is mostly based on 53 # Rose::DB::Object::Metadata::Auto::Pg, after some prodding from 54 # John Siracusa to use his superior SQL code :) 55 56 my $attr_sth = $self->{_cache}->{pg_attr_sth} ||= $dbh->prepare( 57 q{SELECT attname FROM pg_catalog.pg_attribute 58 WHERE attrelid = ? AND attnum = ?} 59 ); 60 61 my $uniq_sth = $self->{_cache}->{pg_uniq_sth} ||= $dbh->prepare( 62 q{SELECT x.indrelid, i.relname, x.indkey 63 FROM 64 pg_catalog.pg_index x 65 JOIN pg_catalog.pg_class c ON c.oid = x.indrelid 66 JOIN pg_catalog.pg_class i ON i.oid = x.indexrelid 67 JOIN pg_catalog.pg_constraint con ON con.conname = i.relname 68 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 69 WHERE 70 x.indisunique = 't' AND 71 c.relkind = 'r' AND 72 i.relkind = 'i' AND 73 con.contype = 'u' AND 74 n.nspname = ? AND 75 c.relname = ?} 76 ); 77 78 $uniq_sth->execute($self->db_schema, $table); 79 while(my $row = $uniq_sth->fetchrow_arrayref) { 80 my ($tableid, $indexname, $col_nums) = @$row; 81 $col_nums =~ s/^\s+//; 82 my @col_nums = split(/\s+/, $col_nums); 83 my @col_names; 84 85 foreach (@col_nums) { 86 $attr_sth->execute($tableid, $_); 87 my $name_aref = $attr_sth->fetchrow_arrayref; 88 push(@col_names, $name_aref->[0]) if $name_aref; 89 } 90 91 if(!@col_names) { 92 warn "Failed to parse UNIQUE constraint $indexname on $table"; 93 } 94 else { 95 push(@uniqs, [ $indexname => \@col_names ]); 96 } 97 } 98 99 return \@uniqs; 100} 101 102sub _table_comment { 103 my ( $self, $table ) = @_; 104 my ($table_comment) = $self->schema->storage->dbh->selectrow_array( 105 q{SELECT obj_description(oid) 106 FROM pg_class 107 WHERE relname=? AND relnamespace=( 108 SELECT oid FROM pg_namespace WHERE nspname=?) 109 }, undef, $table, $self->db_schema 110 ); 111 return $table_comment 112} 113 114 115sub _column_comment { 116 my ( $self, $table, $column_number ) = @_; 117 my ($table_oid) = $self->schema->storage->dbh->selectrow_array( 118 q{SELECT oid 119 FROM pg_class 120 WHERE relname=? AND relnamespace=( 121 SELECT oid FROM pg_namespace WHERE nspname=?) 122 }, undef, $table, $self->db_schema 123 ); 124 return $self->schema->storage->dbh->selectrow_array('SELECT col_description(?,?)', undef, $table_oid, 125 $column_number ); 126} 127 128# Make sure data_type's that don't need it don't have a 'size' column_info, and 129# set the correct precision for datetime and varbit types. 130sub _columns_info_for { 131 my $self = shift; 132 my ($table) = @_; 133 134 my $result = $self->next::method(@_); 135 136 foreach my $col (keys %$result) { 137 my $data_type = $result->{$col}{data_type}; 138 139 # these types are fixed size 140 if ($data_type =~ 141/^(?:bigint|int8|bigserial|serial8|bit|boolean|bool|box|bytea|cidr|circle|date|double precision|float8|inet|integer|int|int4|line|lseg|macaddr|money|path|point|polygon|real|float4|smallint|int2|serial|serial4|text)\z/i) { 142 delete $result->{$col}{size}; 143 } 144# for datetime types, check if it has a precision or not 145 elsif ($data_type =~ /^(?:interval|time|timestamp)\b/i) { 146 my ($precision) = $self->schema->storage->dbh 147 ->selectrow_array(<<EOF, {}, $table, $col); 148SELECT datetime_precision 149FROM information_schema.columns 150WHERE table_name = ? and column_name = ? 151EOF 152 153 if ($data_type =~ /^time\b/i) { 154 if ((not $precision) || $precision !~ /^\d/) { 155 delete $result->{$col}{size}; 156 } 157 else { 158 my ($integer_datetimes) = $self->schema->storage->dbh 159 ->selectrow_array('show integer_datetimes'); 160 161 my $max_precision = 162 $integer_datetimes =~ /^on\z/i ? 6 : 10; 163 164 if ($precision == $max_precision) { 165 delete $result->{$col}{size}; 166 } 167 else { 168 $result->{$col}{size} = $precision; 169 } 170 } 171 } 172 elsif ((not $precision) || $precision !~ /^\d/ || $precision == 6) { 173 delete $result->{$col}{size}; 174 } 175 else { 176 $result->{$col}{size} = $precision; 177 } 178 } 179 elsif ($data_type =~ /^(?:bit varying|varbit)\z/i) { 180 my ($precision) = $self->schema->storage->dbh 181 ->selectrow_array(<<EOF, {}, $table, $col); 182SELECT character_maximum_length 183FROM information_schema.columns 184WHERE table_name = ? and column_name = ? 185EOF 186 187 $result->{$col}{size} = $precision; 188 } 189 elsif ($data_type =~ /^(?:numeric|decimal)\z/i) { 190 my $size = $result->{$col}{size}; 191 $size =~ s/\s*//g; 192 193 my ($scale, $precision) = split /,/, $size; 194 195 $result->{$col}{size} = [ $precision, $scale ]; 196 } 197 } 198 199 return $result; 200} 201 202sub _extra_column_info { 203 my ($self, $info) = @_; 204 my %extra_info; 205 206 if ($info->{COLUMN_DEF} && $info->{COLUMN_DEF} =~ /\bnextval\(/i) { 207 $extra_info{is_auto_increment} = 1; 208 } 209 210 return \%extra_info; 211} 212 213=head1 SEE ALSO 214 215L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>, 216L<DBIx::Class::Schema::Loader::DBI> 217 218=head1 AUTHOR 219 220See L<DBIx::Class::Schema::Loader/AUTHOR> and L<DBIx::Class::Schema::Loader/CONTRIBUTORS>. 221 222=head1 LICENSE 223 224This library is free software; you can redistribute it and/or modify it under 225the same terms as Perl itself. 226 227=cut 228 2291; 230