tweaked pg sequence discovery error message a bit more
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / Storage / DBI / Pg.pm
CommitLineData
843f8ecd 1package DBIx::Class::Storage::DBI::Pg;
2
3use strict;
4use warnings;
5
4ce3b851 6use base qw/DBIx::Class::Storage::DBI::MultiColumnIn/;
ac45262b 7use mro 'c3';
843f8ecd 8
ac45262b 9use DBD::Pg qw(:pg_types);
843f8ecd 10
ac45262b 11# Ask for a DBD::Pg with array support
c70c716e 12warn "DBD::Pg 2.9.2 or greater is strongly recommended\n"
ac45262b 13 if ($DBD::Pg::VERSION < 2.009002); # pg uses (used?) version::qv()
17614944 14
e96a93df 15sub with_deferred_fk_checks {
16 my ($self, $sub) = @_;
17
9ae966b9 18 $self->_get_dbh->do('SET CONSTRAINTS ALL DEFERRED');
e96a93df 19 $sub->();
20}
21
843f8ecd 22sub last_insert_id {
ca48cd7d 23 my ($self,$source,$col) = @_;
0063119f 24 my $seq = ( $source->column_info($col)->{sequence} ||= $self->dbh_do('_dbh_get_autoinc_seq', $source, $col) )
5f70776f 25 or $self->throw_exception( "could not determine sequence for "
26 . $source->name
27 . ".$col, please consider adding a "
28 . "schema-qualified sequence to its column info"
29 );
9a0b7b26 30
31 $self->_dbh_last_insert_id ($self->_dbh, $seq);
0680ac39 32}
33
9a0b7b26 34# there seems to be absolutely no reason to have this as a separate method,
35# but leaving intact in case someone is already overriding it
36sub _dbh_last_insert_id {
37 my ($self, $dbh, $seq) = @_;
38 $dbh->last_insert_id(undef, undef, undef, undef, {sequence => $seq});
39}
40
41
d4f16b21 42sub _dbh_get_autoinc_seq {
0063119f 43 my ($self, $dbh, $source, $col) = @_;
44
45 my $schema;
46 my $table = $source->name;
47
48 # deref table name if it needs it
49 $table = $$table
50 if ref $table eq 'SCALAR';
51
52 # parse out schema name if present
53 if( $table =~ /^(.+)\.(.+)$/ ) {
54 ( $schema, $table ) = ( $1, $2 );
55 }
0680ac39 56
20f43d0c 57 my $sqlmaker = $self->sql_maker;
58 local $sqlmaker->{bindtype} = 'normal';
59
0063119f 60 my ($where, @bind) = $sqlmaker->where ({
20f43d0c 61 'a.attnum' => {'>', 0},
62 'c.relname' => $table,
63 'a.attname' => $col,
64 -not_bool => 'a.attisdropped',
65 (defined $schema && length $schema)
66 ? ( 'n.nspname' => $schema )
67 : ( -bool => \'pg_catalog.pg_table_is_visible(c.oid)' )
68 });
5e14a204 69
70 my ($seq_expr) = $dbh->selectrow_array(<<EOS,undef,@bind);
20f43d0c 71
5e14a204 72SELECT
73 (SELECT pg_catalog.pg_get_expr(d.adbin, d.adrelid)
74 FROM pg_catalog.pg_attrdef d
75 WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)
76FROM pg_catalog.pg_class c
0063119f 77 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
5e14a204 78 JOIN pg_catalog.pg_attribute a ON a.attrelid = c.oid
20f43d0c 79$where
80
5e14a204 81EOS
82
c20066e6 83 # if no default value is set on the column, or if we can't parse the
84 # default value as a sequence, throw.
85 unless ( defined $seq_expr and $seq_expr =~ /^nextval\(+'([^']+)'::(?:text|regclass)\)/i ){
20f43d0c 86 $seq_expr = '' unless defined $seq_expr;
c20066e6 87 $schema = "$schema." if defined $schema && length $schema;
88 $self->throw_exception( "no sequence found for $schema$table.$col, check table definition, "
89 . "or explicitly set the 'sequence' for this column in the "
90 . $source->source_name
91 . " class"
92 );
20f43d0c 93 }
5e14a204 94
95 return $1;
843f8ecd 96}
97
98sub get_autoinc_seq {
ca48cd7d 99 my ($self,$source,$col) = @_;
d4daee7b 100
843f8ecd 101}
102
4f533e8c 103sub sqlt_type {
104 return 'PostgreSQL';
105}
106
45fa8288 107sub datetime_parser_type { return "DateTime::Format::Pg"; }
108
a71859b4 109sub bind_attribute_by_data_type {
110 my ($self,$data_type) = @_;
111
112 my $bind_attributes = {
eda28767 113 bytea => { pg_type => DBD::Pg::PG_BYTEA },
5ba88f68 114 blob => { pg_type => DBD::Pg::PG_BYTEA },
a71859b4 115 };
d4daee7b 116
a71859b4 117 if( defined $bind_attributes->{$data_type} ) {
9fdf90df 118 return $bind_attributes->{$data_type};
a71859b4 119 }
120 else {
121 return;
122 }
123}
124
f04b2839 125sub _sequence_fetch {
126 my ( $self, $type, $seq ) = @_;
9ae966b9 127 my ($id) = $self->_get_dbh->selectrow_array("SELECT nextval('${seq}')");
f04b2839 128 return $id;
129}
130
adb3554a 131sub _svp_begin {
eeb8cfeb 132 my ($self, $name) = @_;
adb3554a 133
9ae966b9 134 $self->_get_dbh->pg_savepoint($name);
adb3554a 135}
136
137sub _svp_release {
eeb8cfeb 138 my ($self, $name) = @_;
adb3554a 139
9ae966b9 140 $self->_get_dbh->pg_release($name);
adb3554a 141}
142
143sub _svp_rollback {
eeb8cfeb 144 my ($self, $name) = @_;
adb3554a 145
9ae966b9 146 $self->_get_dbh->pg_rollback_to($name);
adb3554a 147}
148
843f8ecd 1491;
150
fd159e2a 151__END__
152
75d07914 153=head1 NAME
843f8ecd 154
155DBIx::Class::Storage::DBI::Pg - Automatic primary key class for PostgreSQL
156
157=head1 SYNOPSIS
158
159 # In your table classes
160 __PACKAGE__->load_components(qw/PK::Auto Core/);
161 __PACKAGE__->set_primary_key('id');
162 __PACKAGE__->sequence('mysequence');
163
164=head1 DESCRIPTION
165
166This class implements autoincrements for PostgreSQL.
167
7c0176a1 168=head1 POSTGRESQL SCHEMA SUPPORT
169
4f609014 170This driver supports multiple PostgreSQL schemas, with one caveat: for
6ff1d58c 171performance reasons, data about the search path, sequence names, and
172so forth is queried as needed and CACHED for subsequent uses.
7c0176a1 173
4f609014 174For this reason, once your schema is instantiated, you should not
175change the PostgreSQL schema search path for that schema's database
176connection. If you do, Bad Things may happen.
177
178You should do any necessary manipulation of the search path BEFORE
179instantiating your schema object, or as part of the on_connect_do
180option to connect(), for example:
7c0176a1 181
182 my $schema = My::Schema->connect
183 ( $dsn,$user,$pass,
184 { on_connect_do =>
185 [ 'SET search_path TO myschema, foo, public' ],
186 },
187 );
188
7ff926e6 189=head1 AUTHORS
7c0176a1 190
7ff926e6 191See L<DBIx::Class/CONTRIBUTORS>
843f8ecd 192
193=head1 LICENSE
194
195You may distribute this code under the same terms as Perl itself.
196
197=cut