• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /macosx-10.9.5/CPANInternal-140/DBIx-Class-Schema-Loader-0.05003/lib/DBIx/Class/Schema/Loader/DBI/
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