| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package DBIx::Class::Storage::DBI; | 
| 2 |  |  |  |  |  |  | # -*- mode: cperl; cperl-indent-level: 2 -*- | 
| 3 |  |  |  |  |  |  |  | 
| 4 | 266 |  |  | 266 |  | 196444 | use strict; | 
|  | 266 |  |  |  |  | 615 |  | 
|  | 266 |  |  |  |  | 8258 |  | 
| 5 | 266 |  |  | 266 |  | 1179 | use warnings; | 
|  | 266 |  |  |  |  | 517 |  | 
|  | 266 |  |  |  |  | 9711 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 | 266 |  |  | 266 |  | 1148 | use base qw/DBIx::Class::Storage::DBIHacks DBIx::Class::Storage/; | 
|  | 266 |  |  |  |  | 525 |  | 
|  | 266 |  |  |  |  | 152296 |  | 
| 8 | 266 |  |  | 266 |  | 1954 | use mro 'c3'; | 
|  | 266 |  |  |  |  | 620 |  | 
|  | 266 |  |  |  |  | 1421 |  | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 266 |  |  | 266 |  | 8729 | use DBIx::Class::Carp; | 
|  | 266 |  |  |  |  | 589 |  | 
|  | 266 |  |  |  |  | 1562 |  | 
| 11 | 266 |  |  | 266 |  | 1409 | use Scalar::Util qw/refaddr weaken reftype blessed/; | 
|  | 266 |  |  |  |  | 617 |  | 
|  | 266 |  |  |  |  | 17232 |  | 
| 12 | 266 |  |  | 266 |  | 1254 | use List::Util qw/first/; | 
|  | 266 |  |  |  |  | 560 |  | 
|  | 266 |  |  |  |  | 13679 |  | 
| 13 | 266 |  |  | 266 |  | 1274 | use Context::Preserve 'preserve_context'; | 
|  | 266 |  |  |  |  | 570 |  | 
|  | 266 |  |  |  |  | 10865 |  | 
| 14 | 266 |  |  | 266 |  | 1232 | use Try::Tiny; | 
|  | 266 |  |  |  |  | 546 |  | 
|  | 266 |  |  |  |  | 13350 |  | 
| 15 | 266 |  |  | 266 |  | 1238 | use SQL::Abstract qw(is_plain_value is_literal_value); | 
|  | 266 |  |  |  |  | 561 |  | 
|  | 266 |  |  |  |  | 11878 |  | 
| 16 | 266 |  |  | 266 |  | 1195 | use DBIx::Class::_Util qw(quote_sub perlstring serialize detected_reinvoked_destructor); | 
|  | 266 |  |  |  |  | 763 |  | 
|  | 266 |  |  |  |  | 13892 |  | 
| 17 | 266 |  |  | 266 |  | 1247 | use namespace::clean; | 
|  | 266 |  |  |  |  | 562 |  | 
|  | 266 |  |  |  |  | 1413 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | # default cursor class, overridable in connect_info attributes | 
| 20 |  |  |  |  |  |  | __PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor'); | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors('inherited' => qw/ | 
| 23 |  |  |  |  |  |  | sql_limit_dialect sql_quote_char sql_name_sep | 
| 24 |  |  |  |  |  |  | /); | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors('component_class' => qw/sql_maker_class datetime_parser_type/); | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | __PACKAGE__->sql_maker_class('DBIx::Class::SQLMaker'); | 
| 29 |  |  |  |  |  |  | __PACKAGE__->datetime_parser_type('DateTime::Format::MySQL'); # historic default | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | __PACKAGE__->sql_name_sep('.'); | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors('simple' => qw/ | 
| 34 |  |  |  |  |  |  | _connect_info _dbic_connect_attributes _driver_determined | 
| 35 |  |  |  |  |  |  | _dbh _dbh_details _conn_pid _sql_maker _sql_maker_opts _dbh_autocommit | 
| 36 |  |  |  |  |  |  | _perform_autoinc_retrieval _autoinc_supplied_for_op | 
| 37 |  |  |  |  |  |  | /); | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | # the values for these accessors are picked out (and deleted) from | 
| 40 |  |  |  |  |  |  | # the attribute hashref passed to connect_info | 
| 41 |  |  |  |  |  |  | my @storage_options = qw/ | 
| 42 |  |  |  |  |  |  | on_connect_call on_disconnect_call on_connect_do on_disconnect_do | 
| 43 |  |  |  |  |  |  | disable_sth_caching unsafe auto_savepoint | 
| 44 |  |  |  |  |  |  | /; | 
| 45 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors('simple' => @storage_options); | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  |  | 
| 48 |  |  |  |  |  |  | # capability definitions, using a 2-tiered accessor system | 
| 49 |  |  |  |  |  |  | # The rationale is: | 
| 50 |  |  |  |  |  |  | # | 
| 51 |  |  |  |  |  |  | # A driver/user may define _use_X, which blindly without any checks says: | 
| 52 |  |  |  |  |  |  | # "(do not) use this capability", (use_dbms_capability is an "inherited" | 
| 53 |  |  |  |  |  |  | # type accessor) | 
| 54 |  |  |  |  |  |  | # | 
| 55 |  |  |  |  |  |  | # If _use_X is undef, _supports_X is then queried. This is a "simple" style | 
| 56 |  |  |  |  |  |  | # accessor, which in turn calls _determine_supports_X, and stores the return | 
| 57 |  |  |  |  |  |  | # in a special slot on the storage object, which is wiped every time a $dbh | 
| 58 |  |  |  |  |  |  | # reconnection takes place (it is not guaranteed that upon reconnection we | 
| 59 |  |  |  |  |  |  | # will get the same rdbms version). _determine_supports_X does not need to | 
| 60 |  |  |  |  |  |  | # exist on a driver, as we ->can for it before calling. | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | my @capabilities = (qw/ | 
| 63 |  |  |  |  |  |  | insert_returning | 
| 64 |  |  |  |  |  |  | insert_returning_bound | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | multicolumn_in | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | placeholders | 
| 69 |  |  |  |  |  |  | typeless_placeholders | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | join_optimizer | 
| 72 |  |  |  |  |  |  | /); | 
| 73 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors( dbms_capability => map { "_supports_$_" } @capabilities ); | 
| 74 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors( use_dbms_capability => map { "_use_$_" } (@capabilities ) ); | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | # on by default, not strictly a capability (pending rewrite) | 
| 77 |  |  |  |  |  |  | __PACKAGE__->_use_join_optimizer (1); | 
| 78 | 0 |  |  | 0 |  | 0 | sub _determine_supports_join_optimizer { 1 }; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | # Each of these methods need _determine_driver called before itself | 
| 81 |  |  |  |  |  |  | # in order to function reliably. We also need to separate accessors | 
| 82 |  |  |  |  |  |  | # from plain old method calls, since an accessor called as a setter | 
| 83 |  |  |  |  |  |  | # does *not* need the driver determination loop fired (and in fact | 
| 84 |  |  |  |  |  |  | # can produce hard to find bugs, like e.g. losing on_connect_* | 
| 85 |  |  |  |  |  |  | # semantics on fresh connections) | 
| 86 |  |  |  |  |  |  | # | 
| 87 |  |  |  |  |  |  | # The construct below is simply a parameterized around() | 
| 88 |  |  |  |  |  |  | my $storage_accessor_idx = { map { $_ => 1 } qw( | 
| 89 |  |  |  |  |  |  | sqlt_type | 
| 90 |  |  |  |  |  |  | datetime_parser_type | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | sql_maker | 
| 93 |  |  |  |  |  |  | cursor_class | 
| 94 |  |  |  |  |  |  | )}; | 
| 95 |  |  |  |  |  |  | for my $meth (keys %$storage_accessor_idx, qw( | 
| 96 |  |  |  |  |  |  | deployment_statements | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | build_datetime_parser | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | txn_begin | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | insert | 
| 103 |  |  |  |  |  |  | update | 
| 104 |  |  |  |  |  |  | delete | 
| 105 |  |  |  |  |  |  | select | 
| 106 |  |  |  |  |  |  | select_single | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | _insert_bulk | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | with_deferred_fk_checks | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | get_use_dbms_capability | 
| 113 |  |  |  |  |  |  | get_dbms_capability | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | _server_info | 
| 116 |  |  |  |  |  |  | _get_server_version | 
| 117 |  |  |  |  |  |  | )) { | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | my $orig = __PACKAGE__->can ($meth) | 
| 120 |  |  |  |  |  |  | or die "$meth is not a ::Storage::DBI method!"; | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | my $is_getter = $storage_accessor_idx->{$meth} ? 0 : 1; | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | quote_sub | 
| 125 |  |  |  |  |  |  | __PACKAGE__ ."::$meth", sprintf( <<'EOC', $is_getter, perlstring $meth ), { '$orig' => \$orig }; | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | if ( | 
| 128 |  |  |  |  |  |  | # only fire when invoked on an instance, a valid class-based invocation | 
| 129 |  |  |  |  |  |  | # would e.g. be setting a default for an inherited accessor | 
| 130 |  |  |  |  |  |  | ref $_[0] | 
| 131 |  |  |  |  |  |  | and | 
| 132 |  |  |  |  |  |  | ! $_[0]->{_driver_determined} | 
| 133 |  |  |  |  |  |  | and | 
| 134 |  |  |  |  |  |  | ! $_[0]->{_in_determine_driver} | 
| 135 |  |  |  |  |  |  | and | 
| 136 |  |  |  |  |  |  | # if this is a known *setter* - just set it, no need to connect | 
| 137 |  |  |  |  |  |  | # and determine the driver | 
| 138 |  |  |  |  |  |  | ( %1$s or @_ <= 1 ) | 
| 139 |  |  |  |  |  |  | and | 
| 140 |  |  |  |  |  |  | # Only try to determine stuff if we have *something* that either is or can | 
| 141 |  |  |  |  |  |  | # provide a DSN. Allows for bare $schema's generated with a plain ->connect() | 
| 142 |  |  |  |  |  |  | # to still be marginally useful | 
| 143 |  |  |  |  |  |  | $_[0]->_dbi_connect_info->[0] | 
| 144 |  |  |  |  |  |  | ) { | 
| 145 |  |  |  |  |  |  | $_[0]->_determine_driver; | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | # work around http://rt.perl.org/rt3/Public/Bug/Display.html?id=35878 | 
| 148 |  |  |  |  |  |  | goto $_[0]->can(%2$s) unless DBIx::Class::_ENV_::BROKEN_GOTO; | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | my $cref = $_[0]->can(%2$s); | 
| 151 |  |  |  |  |  |  | goto $cref; | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | goto $orig; | 
| 155 |  |  |  |  |  |  | EOC | 
| 156 |  |  |  |  |  |  | } | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | =head1 NAME | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | DBIx::Class::Storage::DBI - DBI storage handler | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | my $schema = MySchema->connect('dbi:SQLite:my.db'); | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | $schema->storage->debug(1); | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | my @stuff = $schema->storage->dbh_do( | 
| 169 |  |  |  |  |  |  | sub { | 
| 170 |  |  |  |  |  |  | my ($storage, $dbh, @args) = @_; | 
| 171 |  |  |  |  |  |  | $dbh->do("DROP TABLE authors"); | 
| 172 |  |  |  |  |  |  | }, | 
| 173 |  |  |  |  |  |  | @column_list | 
| 174 |  |  |  |  |  |  | ); | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | $schema->resultset('Book')->search({ | 
| 177 |  |  |  |  |  |  | written_on => $schema->storage->datetime_parser->format_datetime(DateTime->now) | 
| 178 |  |  |  |  |  |  | }); | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | This class represents the connection to an RDBMS via L.  See | 
| 183 |  |  |  |  |  |  | L for general information.  This pod only | 
| 184 |  |  |  |  |  |  | documents DBI-specific methods and behaviors. | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | =head1 METHODS | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | =cut | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  | sub new { | 
| 191 | 457 |  |  | 457 | 1 | 5104 | my $new = shift->next::method(@_); | 
| 192 |  |  |  |  |  |  |  | 
| 193 | 457 |  |  |  |  | 1881 | $new->_sql_maker_opts({}); | 
| 194 | 457 |  |  |  |  | 33990 | $new->_dbh_details({}); | 
| 195 | 457 |  |  |  |  | 32211 | $new->{_in_do_block} = 0; | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | # read below to see what this does | 
| 198 | 457 |  |  |  |  | 1641 | $new->_arm_global_destructor; | 
| 199 |  |  |  |  |  |  |  | 
| 200 | 457 |  |  |  |  | 1203 | $new; | 
| 201 |  |  |  |  |  |  | } | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | # This is hack to work around perl shooting stuff in random | 
| 204 |  |  |  |  |  |  | # order on exit(). If we do not walk the remaining storage | 
| 205 |  |  |  |  |  |  | # objects in an END block, there is a *small but real* chance | 
| 206 |  |  |  |  |  |  | # of a fork()ed child to kill the parent's shared DBI handle, | 
| 207 |  |  |  |  |  |  | # *before perl reaches the DESTROY in this package* | 
| 208 |  |  |  |  |  |  | # Yes, it is ugly and effective. | 
| 209 |  |  |  |  |  |  | # Additionally this registry is used by the CLONE method to | 
| 210 |  |  |  |  |  |  | # make sure no handles are shared between threads | 
| 211 |  |  |  |  |  |  | { | 
| 212 |  |  |  |  |  |  | my %seek_and_destroy; | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  | sub _arm_global_destructor { | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  | # quick "garbage collection" pass - prevents the registry | 
| 217 |  |  |  |  |  |  | # from slowly growing with a bunch of undef-valued keys | 
| 218 |  |  |  |  |  |  | defined $seek_and_destroy{$_} or delete $seek_and_destroy{$_} | 
| 219 | 457 |  | 66 | 457 |  | 2664 | for keys %seek_and_destroy; | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | weaken ( | 
| 222 | 457 |  |  |  |  | 2615 | $seek_and_destroy{ refaddr($_[0]) } = $_[0] | 
| 223 |  |  |  |  |  |  | ); | 
| 224 |  |  |  |  |  |  | } | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | END { | 
| 227 | 263 |  |  | 263 |  | 13041706 | local $?; # just in case the DBI destructor changes it somehow | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | # destroy just the object if not native to this process | 
| 230 | 263 |  |  |  |  | 1275 | $_->_verify_pid for (grep | 
| 231 | 231 |  |  |  |  | 2070 | { defined $_ } | 
| 232 |  |  |  |  |  |  | values %seek_and_destroy | 
| 233 |  |  |  |  |  |  | ); | 
| 234 |  |  |  |  |  |  | } | 
| 235 |  |  |  |  |  |  |  | 
| 236 |  |  |  |  |  |  | sub CLONE { | 
| 237 |  |  |  |  |  |  | # As per DBI's recommendation, DBIC disconnects all handles as | 
| 238 |  |  |  |  |  |  | # soon as possible (DBIC will reconnect only on demand from within | 
| 239 |  |  |  |  |  |  | # the thread) | 
| 240 | 0 |  |  | 0 |  | 0 | my @instances = grep { defined $_ } values %seek_and_destroy; | 
|  | 0 |  |  |  |  | 0 |  | 
| 241 | 0 |  |  |  |  | 0 | %seek_and_destroy = (); | 
| 242 |  |  |  |  |  |  |  | 
| 243 | 0 |  |  |  |  | 0 | for (@instances) { | 
| 244 | 0 |  |  |  |  | 0 | $_->_dbh(undef); | 
| 245 |  |  |  |  |  |  |  | 
| 246 | 0 |  |  |  |  | 0 | $_->transaction_depth(0); | 
| 247 | 0 |  |  |  |  | 0 | $_->savepoints([]); | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | # properly renumber existing refs | 
| 250 | 0 |  |  |  |  | 0 | $_->_arm_global_destructor | 
| 251 |  |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  | } | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  |  | 
| 255 |  |  |  |  |  |  | sub DESTROY { | 
| 256 | 455 | 50 |  | 455 |  | 20125 | return if &detected_reinvoked_destructor; | 
| 257 |  |  |  |  |  |  |  | 
| 258 | 455 |  |  |  |  | 2277 | $_[0]->_verify_pid unless DBIx::Class::_ENV_::BROKEN_FORK; | 
| 259 |  |  |  |  |  |  | # some databases spew warnings on implicit disconnect | 
| 260 | 455 |  |  | 1 |  | 4512 | local $SIG{__WARN__} = sub {}; | 
| 261 | 455 |  |  |  |  | 140527 | $_[0]->_dbh(undef); | 
| 262 |  |  |  |  |  |  |  | 
| 263 |  |  |  |  |  |  | # this op is necessary, since the very last perl runtime statement | 
| 264 |  |  |  |  |  |  | # triggers a global destruction shootout, and the $SIG localization | 
| 265 |  |  |  |  |  |  | # may very well be destroyed before perl actually gets to do the | 
| 266 |  |  |  |  |  |  | # $dbh undef | 
| 267 | 455 |  |  |  |  | 38476 | 1; | 
| 268 |  |  |  |  |  |  | } | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  | # handle pid changes correctly - do not destroy parent's connection | 
| 271 |  |  |  |  |  |  | sub _verify_pid { | 
| 272 |  |  |  |  |  |  |  | 
| 273 | 68334 |  |  | 68334 |  | 122058 | my $pid = $_[0]->_conn_pid; | 
| 274 |  |  |  |  |  |  |  | 
| 275 | 68334 | 100 | 100 |  |  | 386106 | if( defined $pid and $pid != $$ and my $dbh = $_[0]->_dbh ) { | 
|  |  |  | 66 |  |  |  |  | 
| 276 | 24 |  |  |  |  | 2835 | $dbh->{InactiveDestroy} = 1; | 
| 277 | 24 |  |  |  |  | 1325 | $_[0]->_dbh(undef); | 
| 278 | 24 |  |  |  |  | 1036 | $_[0]->transaction_depth(0); | 
| 279 | 24 |  |  |  |  | 4058 | $_[0]->savepoints([]); | 
| 280 |  |  |  |  |  |  | } | 
| 281 |  |  |  |  |  |  |  | 
| 282 | 68334 |  |  |  |  | 104014 | return; | 
| 283 |  |  |  |  |  |  | } | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | =head2 connect_info | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | This method is normally called by L, which | 
| 288 |  |  |  |  |  |  | encapsulates its argument list in an arrayref before passing them here. | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | The argument list may contain: | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | =over | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | =item * | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | The same 4-element argument set one would normally pass to | 
| 297 |  |  |  |  |  |  | L, optionally followed by | 
| 298 |  |  |  |  |  |  | L | 
| 299 |  |  |  |  |  |  | recognized by DBIx::Class: | 
| 300 |  |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | $connect_info_args = [ $dsn, $user, $password, \%dbi_attributes?, \%extra_attributes? ]; | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | =item * | 
| 304 |  |  |  |  |  |  |  | 
| 305 |  |  |  |  |  |  | A single code reference which returns a connected | 
| 306 |  |  |  |  |  |  | L optionally followed by | 
| 307 |  |  |  |  |  |  | L recognized | 
| 308 |  |  |  |  |  |  | by DBIx::Class: | 
| 309 |  |  |  |  |  |  |  | 
| 310 |  |  |  |  |  |  | $connect_info_args = [ sub { DBI->connect (...) }, \%extra_attributes? ]; | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | =item * | 
| 313 |  |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | A single hashref with all the attributes and the dsn/user/password | 
| 315 |  |  |  |  |  |  | mixed together: | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | $connect_info_args = [{ | 
| 318 |  |  |  |  |  |  | dsn => $dsn, | 
| 319 |  |  |  |  |  |  | user => $user, | 
| 320 |  |  |  |  |  |  | password => $pass, | 
| 321 |  |  |  |  |  |  | %dbi_attributes, | 
| 322 |  |  |  |  |  |  | %extra_attributes, | 
| 323 |  |  |  |  |  |  | }]; | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | $connect_info_args = [{ | 
| 326 |  |  |  |  |  |  | dbh_maker => sub { DBI->connect (...) }, | 
| 327 |  |  |  |  |  |  | %dbi_attributes, | 
| 328 |  |  |  |  |  |  | %extra_attributes, | 
| 329 |  |  |  |  |  |  | }]; | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | This is particularly useful for L based applications, allowing the | 
| 332 |  |  |  |  |  |  | following config (L style): | 
| 333 |  |  |  |  |  |  |  | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | schema_class   App::DB | 
| 336 |  |  |  |  |  |  |  | 
| 337 |  |  |  |  |  |  | dsn          dbi:mysql:database=test | 
| 338 |  |  |  |  |  |  | user         testuser | 
| 339 |  |  |  |  |  |  | password     TestPass | 
| 340 |  |  |  |  |  |  | AutoCommit   1 | 
| 341 |  |  |  |  |  |  |  | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | The C/C/C combination can be substituted by the | 
| 345 |  |  |  |  |  |  | C key whose value is a coderef that returns a connected | 
| 346 |  |  |  |  |  |  | L | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  | =back | 
| 349 |  |  |  |  |  |  |  | 
| 350 |  |  |  |  |  |  | Please note that the L docs recommend that you always explicitly | 
| 351 |  |  |  |  |  |  | set C to either I<0> or I<1>.  L further | 
| 352 |  |  |  |  |  |  | recommends that it be set to I<1>, and that you perform transactions | 
| 353 |  |  |  |  |  |  | via our L method.  L will set it | 
| 354 |  |  |  |  |  |  | to I<1> if you do not do explicitly set it to zero.  This is the default | 
| 355 |  |  |  |  |  |  | for most DBDs. See L for details. | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | =head3 DBIx::Class specific connection attributes | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | In addition to the standard L | 
| 360 |  |  |  |  |  |  | L attributes, DBIx::Class recognizes | 
| 361 |  |  |  |  |  |  | the following connection options. These options can be mixed in with your other | 
| 362 |  |  |  |  |  |  | L connection attributes, or placed in a separate hashref | 
| 363 |  |  |  |  |  |  | (C<\%extra_attributes>) as shown above. | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | Every time C is invoked, any previous settings for | 
| 366 |  |  |  |  |  |  | these options will be cleared before setting the new ones, regardless of | 
| 367 |  |  |  |  |  |  | whether any options are specified in the new C. | 
| 368 |  |  |  |  |  |  |  | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  | =over | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | =item on_connect_do | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | Specifies things to do immediately after connecting or re-connecting to | 
| 375 |  |  |  |  |  |  | the database.  Its value may contain: | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  | =over | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | =item a scalar | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | This contains one SQL statement to execute. | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | =item an array reference | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | This contains SQL statements to execute in order.  Each element contains | 
| 386 |  |  |  |  |  |  | a string or a code reference that returns a string. | 
| 387 |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  | =item a code reference | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | This contains some code to execute.  Unlike code references within an | 
| 391 |  |  |  |  |  |  | array reference, its return value is ignored. | 
| 392 |  |  |  |  |  |  |  | 
| 393 |  |  |  |  |  |  | =back | 
| 394 |  |  |  |  |  |  |  | 
| 395 |  |  |  |  |  |  | =item on_disconnect_do | 
| 396 |  |  |  |  |  |  |  | 
| 397 |  |  |  |  |  |  | Takes arguments in the same form as L and executes them | 
| 398 |  |  |  |  |  |  | immediately before disconnecting from the database. | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | Note, this only runs if you explicitly call L on the | 
| 401 |  |  |  |  |  |  | storage object. | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | =item on_connect_call | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | A more generalized form of L that calls the specified | 
| 406 |  |  |  |  |  |  | C methods in your storage driver. | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | on_connect_do => 'select 1' | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | is equivalent to: | 
| 411 |  |  |  |  |  |  |  | 
| 412 |  |  |  |  |  |  | on_connect_call => [ [ do_sql => 'select 1' ] ] | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | Its values may contain: | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | =over | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =item a scalar | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | Will call the C method. | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | =item a code reference | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | Will execute C<< $code->($storage) >> | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | =item an array reference | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | Each value can be a method name or code reference. | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | =item an array of arrays | 
| 431 |  |  |  |  |  |  |  | 
| 432 |  |  |  |  |  |  | For each array, the first item is taken to be the C method name | 
| 433 |  |  |  |  |  |  | or code reference, and the rest are parameters to it. | 
| 434 |  |  |  |  |  |  |  | 
| 435 |  |  |  |  |  |  | =back | 
| 436 |  |  |  |  |  |  |  | 
| 437 |  |  |  |  |  |  | Some predefined storage methods you may use: | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  | =over | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | =item do_sql | 
| 442 |  |  |  |  |  |  |  | 
| 443 |  |  |  |  |  |  | Executes a SQL string or a code reference that returns a SQL string. This is | 
| 444 |  |  |  |  |  |  | what L and L use. | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | It can take: | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | =over | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | =item a scalar | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | Will execute the scalar as SQL. | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | =item an arrayref | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | Taken to be arguments to L, the SQL string optionally followed by the | 
| 457 |  |  |  |  |  |  | attributes hashref and bind values. | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | =item a code reference | 
| 460 |  |  |  |  |  |  |  | 
| 461 |  |  |  |  |  |  | Will execute C<< $code->($storage) >> and execute the return array refs as | 
| 462 |  |  |  |  |  |  | above. | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =back | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | =item datetime_setup | 
| 467 |  |  |  |  |  |  |  | 
| 468 |  |  |  |  |  |  | Execute any statements necessary to initialize the database session to return | 
| 469 |  |  |  |  |  |  | and accept datetime/timestamp values used with | 
| 470 |  |  |  |  |  |  | L. | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  | Only necessary for some databases, see your specific storage driver for | 
| 473 |  |  |  |  |  |  | implementation details. | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | =back | 
| 476 |  |  |  |  |  |  |  | 
| 477 |  |  |  |  |  |  | =item on_disconnect_call | 
| 478 |  |  |  |  |  |  |  | 
| 479 |  |  |  |  |  |  | Takes arguments in the same form as L and executes them | 
| 480 |  |  |  |  |  |  | immediately before disconnecting from the database. | 
| 481 |  |  |  |  |  |  |  | 
| 482 |  |  |  |  |  |  | Calls the C methods as opposed to the | 
| 483 |  |  |  |  |  |  | C methods called by L. | 
| 484 |  |  |  |  |  |  |  | 
| 485 |  |  |  |  |  |  | Note, this only runs if you explicitly call L on the | 
| 486 |  |  |  |  |  |  | storage object. | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | =item disable_sth_caching | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | If set to a true value, this option will disable the caching of | 
| 491 |  |  |  |  |  |  | statement handles via L. | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | =item limit_dialect | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | Sets a specific SQL::Abstract::Limit-style limit dialect, overriding the | 
| 496 |  |  |  |  |  |  | default L setting of the storage (if any). For a list | 
| 497 |  |  |  |  |  |  | of available limit dialects see L. | 
| 498 |  |  |  |  |  |  |  | 
| 499 |  |  |  |  |  |  | =item quote_names | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | When true automatically sets L and L to the characters | 
| 502 |  |  |  |  |  |  | appropriate for your particular RDBMS. This option is preferred over specifying | 
| 503 |  |  |  |  |  |  | L directly. | 
| 504 |  |  |  |  |  |  |  | 
| 505 |  |  |  |  |  |  | =item quote_char | 
| 506 |  |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  | Specifies what characters to use to quote table and column names. | 
| 508 |  |  |  |  |  |  |  | 
| 509 |  |  |  |  |  |  | C expects either a single character, in which case is it | 
| 510 |  |  |  |  |  |  | is placed on either side of the table/column name, or an arrayref of length | 
| 511 |  |  |  |  |  |  | 2 in which case the table/column name is placed between the elements. | 
| 512 |  |  |  |  |  |  |  | 
| 513 |  |  |  |  |  |  | For example under MySQL you should use C<< quote_char => '`' >>, and for | 
| 514 |  |  |  |  |  |  | SQL Server you should use C<< quote_char => [qw/[ ]/] >>. | 
| 515 |  |  |  |  |  |  |  | 
| 516 |  |  |  |  |  |  | =item name_sep | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | This parameter is only useful in conjunction with C, and is used to | 
| 519 |  |  |  |  |  |  | specify the character that separates elements (schemas, tables, columns) from | 
| 520 |  |  |  |  |  |  | each other. If unspecified it defaults to the most commonly used C<.>. | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | =item unsafe | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | This Storage driver normally installs its own C, sets | 
| 525 |  |  |  |  |  |  | C and C on, and sets C off on | 
| 526 |  |  |  |  |  |  | all database handles, including those supplied by a coderef.  It does this | 
| 527 |  |  |  |  |  |  | so that it can have consistent and useful error behavior. | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | If you set this option to a true value, Storage will not do its usual | 
| 530 |  |  |  |  |  |  | modifications to the database handle's attributes, and instead relies on | 
| 531 |  |  |  |  |  |  | the settings in your connect_info DBI options (or the values you set in | 
| 532 |  |  |  |  |  |  | your connection coderef, in the case that you are connecting via coderef). | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | Note that your custom settings can cause Storage to malfunction, | 
| 535 |  |  |  |  |  |  | especially if you set a C handler that suppresses exceptions | 
| 536 |  |  |  |  |  |  | and/or disable C. | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | =item auto_savepoint | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | If this option is true, L will use savepoints when nesting | 
| 541 |  |  |  |  |  |  | transactions, making it possible to recover from failure in the inner | 
| 542 |  |  |  |  |  |  | transaction without having to abort all outer transactions. | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | =item cursor_class | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | Use this argument to supply a cursor class other than the default | 
| 547 |  |  |  |  |  |  | L. | 
| 548 |  |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | =back | 
| 550 |  |  |  |  |  |  |  | 
| 551 |  |  |  |  |  |  | Some real-life examples of arguments to L and | 
| 552 |  |  |  |  |  |  | L | 
| 553 |  |  |  |  |  |  |  | 
| 554 |  |  |  |  |  |  | # Simple SQLite connection | 
| 555 |  |  |  |  |  |  | ->connect_info([ 'dbi:SQLite:./foo.db' ]); | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | # Connect via subref | 
| 558 |  |  |  |  |  |  | ->connect_info([ sub { DBI->connect(...) } ]); | 
| 559 |  |  |  |  |  |  |  | 
| 560 |  |  |  |  |  |  | # Connect via subref in hashref | 
| 561 |  |  |  |  |  |  | ->connect_info([{ | 
| 562 |  |  |  |  |  |  | dbh_maker => sub { DBI->connect(...) }, | 
| 563 |  |  |  |  |  |  | on_connect_do => 'alter session ...', | 
| 564 |  |  |  |  |  |  | }]); | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | # A bit more complicated | 
| 567 |  |  |  |  |  |  | ->connect_info( | 
| 568 |  |  |  |  |  |  | [ | 
| 569 |  |  |  |  |  |  | 'dbi:Pg:dbname=foo', | 
| 570 |  |  |  |  |  |  | 'postgres', | 
| 571 |  |  |  |  |  |  | 'my_pg_password', | 
| 572 |  |  |  |  |  |  | { AutoCommit => 1 }, | 
| 573 |  |  |  |  |  |  | { quote_char => q{"} }, | 
| 574 |  |  |  |  |  |  | ] | 
| 575 |  |  |  |  |  |  | ); | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | # Equivalent to the previous example | 
| 578 |  |  |  |  |  |  | ->connect_info( | 
| 579 |  |  |  |  |  |  | [ | 
| 580 |  |  |  |  |  |  | 'dbi:Pg:dbname=foo', | 
| 581 |  |  |  |  |  |  | 'postgres', | 
| 582 |  |  |  |  |  |  | 'my_pg_password', | 
| 583 |  |  |  |  |  |  | { AutoCommit => 1, quote_char => q{"}, name_sep => q{.} }, | 
| 584 |  |  |  |  |  |  | ] | 
| 585 |  |  |  |  |  |  | ); | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | # Same, but with hashref as argument | 
| 588 |  |  |  |  |  |  | # See parse_connect_info for explanation | 
| 589 |  |  |  |  |  |  | ->connect_info( | 
| 590 |  |  |  |  |  |  | [{ | 
| 591 |  |  |  |  |  |  | dsn         => 'dbi:Pg:dbname=foo', | 
| 592 |  |  |  |  |  |  | user        => 'postgres', | 
| 593 |  |  |  |  |  |  | password    => 'my_pg_password', | 
| 594 |  |  |  |  |  |  | AutoCommit  => 1, | 
| 595 |  |  |  |  |  |  | quote_char  => q{"}, | 
| 596 |  |  |  |  |  |  | name_sep    => q{.}, | 
| 597 |  |  |  |  |  |  | }] | 
| 598 |  |  |  |  |  |  | ); | 
| 599 |  |  |  |  |  |  |  | 
| 600 |  |  |  |  |  |  | # Subref + DBIx::Class-specific connection options | 
| 601 |  |  |  |  |  |  | ->connect_info( | 
| 602 |  |  |  |  |  |  | [ | 
| 603 |  |  |  |  |  |  | sub { DBI->connect(...) }, | 
| 604 |  |  |  |  |  |  | { | 
| 605 |  |  |  |  |  |  | quote_char => q{`}, | 
| 606 |  |  |  |  |  |  | name_sep => q{@}, | 
| 607 |  |  |  |  |  |  | on_connect_do => ['SET search_path TO myschema,otherschema,public'], | 
| 608 |  |  |  |  |  |  | disable_sth_caching => 1, | 
| 609 |  |  |  |  |  |  | }, | 
| 610 |  |  |  |  |  |  | ] | 
| 611 |  |  |  |  |  |  | ); | 
| 612 |  |  |  |  |  |  |  | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  |  | 
| 615 |  |  |  |  |  |  | =cut | 
| 616 |  |  |  |  |  |  |  | 
| 617 |  |  |  |  |  |  | sub connect_info { | 
| 618 | 453 |  |  | 453 | 1 | 4006 | my ($self, $info) = @_; | 
| 619 |  |  |  |  |  |  |  | 
| 620 | 453 | 100 |  |  |  | 1644 | return $self->_connect_info if !$info; | 
| 621 |  |  |  |  |  |  |  | 
| 622 | 449 |  |  |  |  | 1670 | $self->_connect_info($info); # copy for _connect_info | 
| 623 |  |  |  |  |  |  |  | 
| 624 | 449 | 50 |  |  |  | 33458 | $info = $self->_normalize_connect_info($info) | 
| 625 |  |  |  |  |  |  | if ref $info eq 'ARRAY'; | 
| 626 |  |  |  |  |  |  |  | 
| 627 |  |  |  |  |  |  | my %attrs = ( | 
| 628 | 449 | 50 |  |  |  | 1731 | %{ $self->_default_dbi_connect_attributes || {} }, | 
| 629 | 449 | 100 |  |  |  | 809 | %{ $info->{attributes} || {} }, | 
|  | 449 |  |  |  |  | 2638 |  | 
| 630 |  |  |  |  |  |  | ); | 
| 631 |  |  |  |  |  |  |  | 
| 632 | 449 |  |  |  |  | 1062 | my @args = @{ $info->{arguments} }; | 
|  | 449 |  |  |  |  | 1565 |  | 
| 633 |  |  |  |  |  |  |  | 
| 634 | 449 | 100 | 66 |  |  | 4246 | if (keys %attrs and ref $args[0] ne 'CODE') { | 
| 635 |  |  |  |  |  |  | carp_unique ( | 
| 636 |  |  |  |  |  |  | 'You provided explicit AutoCommit => 0 in your connection_info. ' | 
| 637 |  |  |  |  |  |  | . 'This is almost universally a bad idea (see the footnotes of ' | 
| 638 |  |  |  |  |  |  | . 'DBIx::Class::Storage::DBI for more info). If you still want to ' | 
| 639 |  |  |  |  |  |  | . 'do this you can set $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK} to disable ' | 
| 640 |  |  |  |  |  |  | . 'this warning.' | 
| 641 | 442 | 50 | 66 |  |  | 1516 | ) if ! $attrs{AutoCommit} and ! $ENV{DBIC_UNSAFE_AUTOCOMMIT_OK}; | 
| 642 |  |  |  |  |  |  |  | 
| 643 | 442 | 50 |  |  |  | 1780 | push @args, \%attrs if keys %attrs; | 
| 644 |  |  |  |  |  |  | } | 
| 645 |  |  |  |  |  |  |  | 
| 646 |  |  |  |  |  |  | # this is the authoritative "always an arrayref" thing fed to DBI->connect | 
| 647 |  |  |  |  |  |  | # OR a single-element coderef-based $dbh factory | 
| 648 | 449 |  |  |  |  | 1844 | $self->_dbi_connect_info(\@args); | 
| 649 |  |  |  |  |  |  |  | 
| 650 |  |  |  |  |  |  | # extract the individual storage options | 
| 651 | 449 |  |  |  |  | 629 | for my $storage_opt (keys %{ $info->{storage_options} }) { | 
|  | 449 |  |  |  |  | 1619 |  | 
| 652 | 454 |  |  |  |  | 1565 | my $value = $info->{storage_options}{$storage_opt}; | 
| 653 |  |  |  |  |  |  |  | 
| 654 | 454 |  |  |  |  | 2007 | $self->$storage_opt($value); | 
| 655 |  |  |  |  |  |  | } | 
| 656 |  |  |  |  |  |  |  | 
| 657 |  |  |  |  |  |  | # Extract the individual sqlmaker options | 
| 658 |  |  |  |  |  |  | # | 
| 659 |  |  |  |  |  |  | # Kill sql_maker/_sql_maker_opts, so we get a fresh one with only | 
| 660 |  |  |  |  |  |  | #  the new set of options | 
| 661 | 449 |  |  |  |  | 33591 | $self->_sql_maker(undef); | 
| 662 | 449 |  |  |  |  | 29930 | $self->_sql_maker_opts({}); | 
| 663 |  |  |  |  |  |  |  | 
| 664 | 449 |  |  |  |  | 698 | for my $sql_maker_opt (keys %{ $info->{sql_maker_options} }) { | 
|  | 449 |  |  |  |  | 1703 |  | 
| 665 | 11 |  |  |  |  | 23 | my $value = $info->{sql_maker_options}{$sql_maker_opt}; | 
| 666 |  |  |  |  |  |  |  | 
| 667 | 11 |  |  |  |  | 44 | $self->_sql_maker_opts->{$sql_maker_opt} = $value; | 
| 668 |  |  |  |  |  |  | } | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | # FIXME - dirty: | 
| 671 |  |  |  |  |  |  | # save attributes in a separate accessor so they are always | 
| 672 |  |  |  |  |  |  | # introspectable, even in case of a CODE $dbhmaker | 
| 673 | 449 |  |  |  |  | 1924 | $self->_dbic_connect_attributes (\%attrs); | 
| 674 |  |  |  |  |  |  |  | 
| 675 | 449 |  |  |  |  | 31000 | return $self->_connect_info; | 
| 676 |  |  |  |  |  |  | } | 
| 677 |  |  |  |  |  |  |  | 
| 678 |  |  |  |  |  |  | sub _dbi_connect_info { | 
| 679 | 1235 |  |  | 1235 |  | 16978 | my $self = shift; | 
| 680 |  |  |  |  |  |  |  | 
| 681 | 1235 | 100 |  |  |  | 6066 | return $self->{_dbi_connect_info} = $_[0] | 
| 682 |  |  |  |  |  |  | if @_; | 
| 683 |  |  |  |  |  |  |  | 
| 684 | 786 |  | 50 |  |  | 4118 | my $conninfo = $self->{_dbi_connect_info} || []; | 
| 685 |  |  |  |  |  |  |  | 
| 686 |  |  |  |  |  |  | # last ditch effort to grab a DSN | 
| 687 | 786 | 100 | 66 |  |  | 2716 | if ( ! defined $conninfo->[0] and $ENV{DBI_DSN} ) { | 
| 688 | 168 |  |  |  |  | 310 | my @new_conninfo = @$conninfo; | 
| 689 | 168 |  |  |  |  | 211 | $new_conninfo[0] = $ENV{DBI_DSN}; | 
| 690 | 168 |  |  |  |  | 200 | $conninfo = \@new_conninfo; | 
| 691 |  |  |  |  |  |  | } | 
| 692 |  |  |  |  |  |  |  | 
| 693 | 786 |  |  |  |  | 2499 | return $conninfo; | 
| 694 |  |  |  |  |  |  | } | 
| 695 |  |  |  |  |  |  |  | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | sub _normalize_connect_info { | 
| 698 | 449 |  |  | 449 |  | 879 | my ($self, $info_arg) = @_; | 
| 699 | 449 |  |  |  |  | 697 | my %info; | 
| 700 |  |  |  |  |  |  |  | 
| 701 | 449 |  |  |  |  | 1702 | my @args = @$info_arg;  # take a shallow copy for further mutilation | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | # combine/pre-parse arguments depending on invocation style | 
| 704 |  |  |  |  |  |  |  | 
| 705 | 449 |  |  |  |  | 714 | my %attrs; | 
| 706 | 449 | 100 |  |  |  | 2444 | if (ref $args[0] eq 'CODE') {     # coderef with optional \%extra_attributes | 
|  |  | 100 |  |  |  |  |  | 
| 707 | 6 | 100 |  |  |  | 13 | %attrs = %{ $args[1] || {} }; | 
|  | 6 |  |  |  |  | 43 |  | 
| 708 | 6 |  |  |  |  | 17 | @args = $args[0]; | 
| 709 |  |  |  |  |  |  | } | 
| 710 |  |  |  |  |  |  | elsif (ref $args[0] eq 'HASH') { # single hashref (i.e. Catalyst config) | 
| 711 | 2 |  |  |  |  | 2 | %attrs = %{$args[0]}; | 
|  | 2 |  |  |  |  | 27 |  | 
| 712 | 2 |  |  |  |  | 4 | @args = (); | 
| 713 | 2 | 100 |  |  |  | 7 | if (my $code = delete $attrs{dbh_maker}) { | 
| 714 | 1 |  |  |  |  | 3 | @args = $code; | 
| 715 |  |  |  |  |  |  |  | 
| 716 | 1 |  |  |  |  | 3 | my @ignored = grep { delete $attrs{$_} } (qw/dsn user password/); | 
|  | 3 |  |  |  |  | 5 |  | 
| 717 | 1 | 50 |  |  |  | 4 | if (@ignored) { | 
| 718 |  |  |  |  |  |  | carp sprintf ( | 
| 719 |  |  |  |  |  |  | 'Attribute(s) %s in connect_info were ignored, as they can not be applied ' | 
| 720 |  |  |  |  |  |  | . "to the result of 'dbh_maker'", | 
| 721 |  |  |  |  |  |  |  | 
| 722 | 1 |  |  |  |  | 2 | join (', ', map { "'$_'" } (@ignored) ), | 
|  | 2 |  |  |  |  | 12 |  | 
| 723 |  |  |  |  |  |  | ); | 
| 724 |  |  |  |  |  |  | } | 
| 725 |  |  |  |  |  |  | } | 
| 726 |  |  |  |  |  |  | else { | 
| 727 | 1 |  |  |  |  | 5 | @args = delete @attrs{qw/dsn user password/}; | 
| 728 |  |  |  |  |  |  | } | 
| 729 |  |  |  |  |  |  | } | 
| 730 |  |  |  |  |  |  | else {                # otherwise assume dsn/user/password + \%attrs + \%extra_attrs | 
| 731 |  |  |  |  |  |  | %attrs = ( | 
| 732 | 441 | 100 |  |  |  | 2343 | % { $args[3] || {} }, | 
| 733 | 441 | 100 |  |  |  | 756 | % { $args[4] || {} }, | 
|  | 441 |  |  |  |  | 3339 |  | 
| 734 |  |  |  |  |  |  | ); | 
| 735 | 441 |  |  |  |  | 1911 | @args = @args[0,1,2]; | 
| 736 |  |  |  |  |  |  | } | 
| 737 |  |  |  |  |  |  |  | 
| 738 | 449 |  |  |  |  | 1397 | $info{arguments} = \@args; | 
| 739 |  |  |  |  |  |  |  | 
| 740 | 449 |  |  |  |  | 2963 | my @storage_opts = grep exists $attrs{$_}, | 
| 741 |  |  |  |  |  |  | @storage_options, 'cursor_class'; | 
| 742 |  |  |  |  |  |  |  | 
| 743 | 418 |  |  |  |  | 1424 | @{ $info{storage_options} }{@storage_opts} = | 
| 744 | 449 | 100 |  |  |  | 1927 | delete @attrs{@storage_opts} if @storage_opts; | 
| 745 |  |  |  |  |  |  |  | 
| 746 | 449 |  |  |  |  | 1774 | my @sql_maker_opts = grep exists $attrs{$_}, | 
| 747 |  |  |  |  |  |  | qw/limit_dialect quote_char name_sep quote_names/; | 
| 748 |  |  |  |  |  |  |  | 
| 749 | 11 |  |  |  |  | 35 | @{ $info{sql_maker_options} }{@sql_maker_opts} = | 
| 750 | 449 | 100 |  |  |  | 1256 | delete @attrs{@sql_maker_opts} if @sql_maker_opts; | 
| 751 |  |  |  |  |  |  |  | 
| 752 | 449 | 100 |  |  |  | 2029 | $info{attributes} = \%attrs if %attrs; | 
| 753 |  |  |  |  |  |  |  | 
| 754 | 449 |  |  |  |  | 1395 | return \%info; | 
| 755 |  |  |  |  |  |  | } | 
| 756 |  |  |  |  |  |  |  | 
| 757 |  |  |  |  |  |  | sub _default_dbi_connect_attributes () { | 
| 758 |  |  |  |  |  |  | +{ | 
| 759 | 451 |  |  | 451 |  | 3695 | AutoCommit => 1, | 
| 760 |  |  |  |  |  |  | PrintError => 0, | 
| 761 |  |  |  |  |  |  | RaiseError => 1, | 
| 762 |  |  |  |  |  |  | ShowErrorStatement => 1, | 
| 763 |  |  |  |  |  |  | }; | 
| 764 |  |  |  |  |  |  | } | 
| 765 |  |  |  |  |  |  |  | 
| 766 |  |  |  |  |  |  | =head2 on_connect_do | 
| 767 |  |  |  |  |  |  |  | 
| 768 |  |  |  |  |  |  | This method is deprecated in favour of setting via L. | 
| 769 |  |  |  |  |  |  |  | 
| 770 |  |  |  |  |  |  | =cut | 
| 771 |  |  |  |  |  |  |  | 
| 772 |  |  |  |  |  |  | =head2 on_disconnect_do | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | This method is deprecated in favour of setting via L. | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | =cut | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | sub _parse_connect_do { | 
| 779 | 488 |  |  | 488 |  | 3332 | my ($self, $type) = @_; | 
| 780 |  |  |  |  |  |  |  | 
| 781 | 488 |  |  |  |  | 2251 | my $val = $self->$type; | 
| 782 | 488 | 100 |  |  |  | 3508 | return () if not defined $val; | 
| 783 |  |  |  |  |  |  |  | 
| 784 | 451 |  |  |  |  | 733 | my @res; | 
| 785 |  |  |  |  |  |  |  | 
| 786 | 451 | 100 |  |  |  | 2590 | if (not ref($val)) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 787 | 7 |  |  |  |  | 24 | push @res, [ 'do_sql', $val ]; | 
| 788 |  |  |  |  |  |  | } elsif (ref($val) eq 'CODE') { | 
| 789 | 442 |  |  |  |  | 1054 | push @res, $val; | 
| 790 |  |  |  |  |  |  | } elsif (ref($val) eq 'ARRAY') { | 
| 791 | 2 |  |  |  |  | 4 | push @res, map { [ 'do_sql', $_ ] } @$val; | 
|  | 6 |  |  |  |  | 11 |  | 
| 792 |  |  |  |  |  |  | } else { | 
| 793 | 0 |  |  |  |  | 0 | $self->throw_exception("Invalid type for $type: ".ref($val)); | 
| 794 |  |  |  |  |  |  | } | 
| 795 |  |  |  |  |  |  |  | 
| 796 | 451 |  |  |  |  | 4083 | return \@res; | 
| 797 |  |  |  |  |  |  | } | 
| 798 |  |  |  |  |  |  |  | 
| 799 |  |  |  |  |  |  | =head2 dbh_do | 
| 800 |  |  |  |  |  |  |  | 
| 801 |  |  |  |  |  |  | Arguments: ($subref | $method_name), @extra_coderef_args? | 
| 802 |  |  |  |  |  |  |  | 
| 803 |  |  |  |  |  |  | Execute the given $subref or $method_name using the new exception-based | 
| 804 |  |  |  |  |  |  | connection management. | 
| 805 |  |  |  |  |  |  |  | 
| 806 |  |  |  |  |  |  | The first two arguments will be the storage object that C was called | 
| 807 |  |  |  |  |  |  | on and a database handle to use.  Any additional arguments will be passed | 
| 808 |  |  |  |  |  |  | verbatim to the called subref as arguments 2 and onwards. | 
| 809 |  |  |  |  |  |  |  | 
| 810 |  |  |  |  |  |  | Using this (instead of $self->_dbh or $self->dbh) ensures correct | 
| 811 |  |  |  |  |  |  | exception handling and reconnection (or failover in future subclasses). | 
| 812 |  |  |  |  |  |  |  | 
| 813 |  |  |  |  |  |  | Your subref should have no side-effects outside of the database, as | 
| 814 |  |  |  |  |  |  | there is the potential for your subref to be partially double-executed | 
| 815 |  |  |  |  |  |  | if the database connection was stale/dysfunctional. | 
| 816 |  |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | Example: | 
| 818 |  |  |  |  |  |  |  | 
| 819 |  |  |  |  |  |  | my @stuff = $schema->storage->dbh_do( | 
| 820 |  |  |  |  |  |  | sub { | 
| 821 |  |  |  |  |  |  | my ($storage, $dbh, @cols) = @_; | 
| 822 |  |  |  |  |  |  | my $cols = join(q{, }, @cols); | 
| 823 |  |  |  |  |  |  | $dbh->selectrow_array("SELECT $cols FROM foo"); | 
| 824 |  |  |  |  |  |  | }, | 
| 825 |  |  |  |  |  |  | @column_list | 
| 826 |  |  |  |  |  |  | ); | 
| 827 |  |  |  |  |  |  |  | 
| 828 |  |  |  |  |  |  | =cut | 
| 829 |  |  |  |  |  |  |  | 
| 830 |  |  |  |  |  |  | sub dbh_do { | 
| 831 | 47304 |  |  | 47304 | 1 | 1816786 | my $self = shift; | 
| 832 | 47304 |  |  |  |  | 46773 | my $run_target = shift; # either a coderef or a method name | 
| 833 |  |  |  |  |  |  |  | 
| 834 |  |  |  |  |  |  | # short circuit when we know there is no need for a runner | 
| 835 |  |  |  |  |  |  | # | 
| 836 |  |  |  |  |  |  | # FIXME - assumption may be wrong | 
| 837 |  |  |  |  |  |  | # the rationale for the txn_depth check is that if this block is a part | 
| 838 |  |  |  |  |  |  | # of a larger transaction, everything up to that point is screwed anyway | 
| 839 |  |  |  |  |  |  | return $self->$run_target($self->_get_dbh, @_) | 
| 840 | 47304 | 100 | 100 |  |  | 251911 | if $self->{_in_do_block} or $self->transaction_depth; | 
| 841 |  |  |  |  |  |  |  | 
| 842 |  |  |  |  |  |  | # take a ref instead of a copy, to preserve @_ aliasing | 
| 843 |  |  |  |  |  |  | # semantics within the coderef, but only if needed | 
| 844 |  |  |  |  |  |  | # (pseudoforking doesn't like this trick much) | 
| 845 | 44299 | 100 |  |  |  | 119797 | my $args = @_ ? \@_ : []; | 
| 846 |  |  |  |  |  |  |  | 
| 847 |  |  |  |  |  |  | DBIx::Class::Storage::BlockRunner->new( | 
| 848 |  |  |  |  |  |  | storage => $self, | 
| 849 |  |  |  |  |  |  | wrap_txn => 0, | 
| 850 |  |  |  |  |  |  | retry_handler => sub { | 
| 851 | 23 | 50 |  | 23 |  | 526 | $_[0]->failed_attempt_count == 1 | 
| 852 |  |  |  |  |  |  | and | 
| 853 |  |  |  |  |  |  | ! $_[0]->storage->connected | 
| 854 |  |  |  |  |  |  | }, | 
| 855 |  |  |  |  |  |  | )->run(sub { | 
| 856 | 44302 |  |  | 44302 |  | 92068 | $self->$run_target ($self->_get_dbh, @$args ) | 
| 857 | 44299 |  |  |  |  | 907881 | }); | 
| 858 |  |  |  |  |  |  | } | 
| 859 |  |  |  |  |  |  |  | 
| 860 |  |  |  |  |  |  | sub txn_do { | 
| 861 | 472 |  |  | 472 | 1 | 7610 | $_[0]->_get_dbh; # connects or reconnects on pid change, necessary to grab correct txn_depth | 
| 862 | 472 |  |  |  |  | 2453 | shift->next::method(@_); | 
| 863 |  |  |  |  |  |  | } | 
| 864 |  |  |  |  |  |  |  | 
| 865 |  |  |  |  |  |  | =head2 disconnect | 
| 866 |  |  |  |  |  |  |  | 
| 867 |  |  |  |  |  |  | Our C method also performs a rollback first if the | 
| 868 |  |  |  |  |  |  | database is not in C mode. | 
| 869 |  |  |  |  |  |  |  | 
| 870 |  |  |  |  |  |  | =cut | 
| 871 |  |  |  |  |  |  |  | 
| 872 |  |  |  |  |  |  | sub disconnect { | 
| 873 |  |  |  |  |  |  |  | 
| 874 | 37 | 100 |  | 37 | 1 | 5682 | if( my $dbh = $_[0]->_dbh ) { | 
| 875 |  |  |  |  |  |  |  | 
| 876 | 20 |  | 100 |  |  | 156 | $_[0]->_do_connection_actions(disconnect_call_ => $_) for ( | 
| 877 |  |  |  |  |  |  | ( $_[0]->on_disconnect_call || () ), | 
| 878 |  |  |  |  |  |  | $_[0]->_parse_connect_do ('on_disconnect_do') | 
| 879 |  |  |  |  |  |  | ); | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | # stops the "implicit rollback on disconnect" warning | 
| 882 | 20 | 50 |  |  |  | 104 | $_[0]->_exec_txn_rollback unless $_[0]->_dbh_autocommit; | 
| 883 |  |  |  |  |  |  |  | 
| 884 | 20 |  |  |  |  | 37 | %{ $dbh->{CachedKids} } = (); | 
|  | 20 |  |  |  |  | 818 |  | 
| 885 | 20 |  |  |  |  | 525 | $dbh->disconnect; | 
| 886 | 20 |  |  |  |  | 1368 | $_[0]->_dbh(undef); | 
| 887 |  |  |  |  |  |  | } | 
| 888 |  |  |  |  |  |  | } | 
| 889 |  |  |  |  |  |  |  | 
| 890 |  |  |  |  |  |  | =head2 with_deferred_fk_checks | 
| 891 |  |  |  |  |  |  |  | 
| 892 |  |  |  |  |  |  | =over 4 | 
| 893 |  |  |  |  |  |  |  | 
| 894 |  |  |  |  |  |  | =item Arguments: C<$coderef> | 
| 895 |  |  |  |  |  |  |  | 
| 896 |  |  |  |  |  |  | =item Return Value: The return value of $coderef | 
| 897 |  |  |  |  |  |  |  | 
| 898 |  |  |  |  |  |  | =back | 
| 899 |  |  |  |  |  |  |  | 
| 900 |  |  |  |  |  |  | Storage specific method to run the code ref with FK checks deferred or | 
| 901 |  |  |  |  |  |  | in MySQL's case disabled entirely. | 
| 902 |  |  |  |  |  |  |  | 
| 903 |  |  |  |  |  |  | =cut | 
| 904 |  |  |  |  |  |  |  | 
| 905 |  |  |  |  |  |  | # Storage subclasses should override this | 
| 906 |  |  |  |  |  |  | sub with_deferred_fk_checks { | 
| 907 |  |  |  |  |  |  | #my ($self, $sub) = @_; | 
| 908 |  |  |  |  |  |  | $_[1]->(); | 
| 909 |  |  |  |  |  |  | } | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | =head2 connected | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | =over | 
| 914 |  |  |  |  |  |  |  | 
| 915 |  |  |  |  |  |  | =item Arguments: none | 
| 916 |  |  |  |  |  |  |  | 
| 917 |  |  |  |  |  |  | =item Return Value: 1|0 | 
| 918 |  |  |  |  |  |  |  | 
| 919 |  |  |  |  |  |  | =back | 
| 920 |  |  |  |  |  |  |  | 
| 921 |  |  |  |  |  |  | Verifies that the current database handle is active and ready to execute | 
| 922 |  |  |  |  |  |  | an SQL statement (e.g. the connection did not get stale, server is still | 
| 923 |  |  |  |  |  |  | answering, etc.) This method is used internally by L. | 
| 924 |  |  |  |  |  |  |  | 
| 925 |  |  |  |  |  |  | =cut | 
| 926 |  |  |  |  |  |  |  | 
| 927 |  |  |  |  |  |  | sub connected { | 
| 928 | 263 | 100 |  | 263 | 1 | 17780 | return 0 unless $_[0]->_seems_connected; | 
| 929 |  |  |  |  |  |  |  | 
| 930 |  |  |  |  |  |  | #be on the safe side | 
| 931 | 149 |  |  |  |  | 1622 | local $_[0]->_dbh->{RaiseError} = 1; | 
| 932 |  |  |  |  |  |  |  | 
| 933 | 149 |  |  |  |  | 2057 | return $_[0]->_ping; | 
| 934 |  |  |  |  |  |  | } | 
| 935 |  |  |  |  |  |  |  | 
| 936 |  |  |  |  |  |  | sub _seems_connected { | 
| 937 | 9932 |  |  | 9932 |  | 24538 | $_[0]->_verify_pid unless DBIx::Class::_ENV_::BROKEN_FORK; | 
| 938 |  |  |  |  |  |  |  | 
| 939 | 9932 |  | 100 |  |  | 80875 | ($_[0]->_dbh || return 0)->FETCH('Active'); | 
| 940 |  |  |  |  |  |  | } | 
| 941 |  |  |  |  |  |  |  | 
| 942 |  |  |  |  |  |  | sub _ping { | 
| 943 | 6 |  | 50 | 6 |  | 56 | ($_[0]->_dbh || return 0)->ping; | 
| 944 |  |  |  |  |  |  | } | 
| 945 |  |  |  |  |  |  |  | 
| 946 |  |  |  |  |  |  | sub ensure_connected { | 
| 947 | 173 | 100 | 50 | 173 | 1 | 7629 | $_[0]->connected || ( $_[0]->_populate_dbh && 1 ); | 
| 948 |  |  |  |  |  |  | } | 
| 949 |  |  |  |  |  |  |  | 
| 950 |  |  |  |  |  |  | =head2 dbh | 
| 951 |  |  |  |  |  |  |  | 
| 952 |  |  |  |  |  |  | Returns a C<$dbh> - a data base handle of class L. The returned handle | 
| 953 |  |  |  |  |  |  | is guaranteed to be healthy by implicitly calling L, and if | 
| 954 |  |  |  |  |  |  | necessary performing a reconnection before returning. Keep in mind that this | 
| 955 |  |  |  |  |  |  | is very B on some database engines. Consider using L | 
| 956 |  |  |  |  |  |  | instead. | 
| 957 |  |  |  |  |  |  |  | 
| 958 |  |  |  |  |  |  | =cut | 
| 959 |  |  |  |  |  |  |  | 
| 960 |  |  |  |  |  |  | sub dbh { | 
| 961 |  |  |  |  |  |  | # maybe save a ping call | 
| 962 | 109 | 100 | 33 | 109 | 1 | 10687 | $_[0]->_dbh | 
| 963 |  |  |  |  |  |  | ? ( $_[0]->ensure_connected and $_[0]->_dbh ) | 
| 964 |  |  |  |  |  |  | : $_[0]->_populate_dbh | 
| 965 |  |  |  |  |  |  | ; | 
| 966 |  |  |  |  |  |  | } | 
| 967 |  |  |  |  |  |  |  | 
| 968 |  |  |  |  |  |  | # this is the internal "get dbh or connect (don't check)" method | 
| 969 |  |  |  |  |  |  | sub _get_dbh { | 
| 970 | 57811 |  |  | 57811 |  | 117312 | $_[0]->_verify_pid unless DBIx::Class::_ENV_::BROKEN_FORK; | 
| 971 | 57811 | 100 |  |  |  | 288924 | $_[0]->_dbh || $_[0]->_populate_dbh; | 
| 972 |  |  |  |  |  |  | } | 
| 973 |  |  |  |  |  |  |  | 
| 974 |  |  |  |  |  |  | # *DELIBERATELY* not a setter (for the time being) | 
| 975 |  |  |  |  |  |  | # Too intertwined with everything else for any kind of sanity | 
| 976 |  |  |  |  |  |  | sub sql_maker { | 
| 977 |  |  |  |  |  |  | my $self = shift; | 
| 978 |  |  |  |  |  |  |  | 
| 979 |  |  |  |  |  |  | $self->throw_exception('sql_maker() is not a setter method') if @_; | 
| 980 |  |  |  |  |  |  |  | 
| 981 |  |  |  |  |  |  | unless ($self->_sql_maker) { | 
| 982 |  |  |  |  |  |  | my $sql_maker_class = $self->sql_maker_class; | 
| 983 |  |  |  |  |  |  |  | 
| 984 |  |  |  |  |  |  | my %opts = %{$self->_sql_maker_opts||{}}; | 
| 985 |  |  |  |  |  |  | my $dialect = | 
| 986 |  |  |  |  |  |  | $opts{limit_dialect} | 
| 987 |  |  |  |  |  |  | || | 
| 988 |  |  |  |  |  |  | $self->sql_limit_dialect | 
| 989 |  |  |  |  |  |  | || | 
| 990 |  |  |  |  |  |  | do { | 
| 991 |  |  |  |  |  |  | my $s_class = (ref $self) || $self; | 
| 992 |  |  |  |  |  |  | carp_unique ( | 
| 993 |  |  |  |  |  |  | "Your storage class ($s_class) does not set sql_limit_dialect and you " | 
| 994 |  |  |  |  |  |  | . 'have not supplied an explicit limit_dialect in your connection_info. ' | 
| 995 |  |  |  |  |  |  | . 'DBIC will attempt to use the GenericSubQ dialect, which works on most ' | 
| 996 |  |  |  |  |  |  | . 'databases but can be (and often is) painfully slow. ' | 
| 997 |  |  |  |  |  |  | . "Please file an RT ticket against '$s_class'" | 
| 998 |  |  |  |  |  |  | ) if $self->_dbi_connect_info->[0]; | 
| 999 |  |  |  |  |  |  |  | 
| 1000 |  |  |  |  |  |  | 'GenericSubQ'; | 
| 1001 |  |  |  |  |  |  | } | 
| 1002 |  |  |  |  |  |  | ; | 
| 1003 |  |  |  |  |  |  |  | 
| 1004 |  |  |  |  |  |  | my ($quote_char, $name_sep); | 
| 1005 |  |  |  |  |  |  |  | 
| 1006 |  |  |  |  |  |  | if ($opts{quote_names}) { | 
| 1007 |  |  |  |  |  |  | $quote_char = (delete $opts{quote_char}) || $self->sql_quote_char || do { | 
| 1008 |  |  |  |  |  |  | my $s_class = (ref $self) || $self; | 
| 1009 |  |  |  |  |  |  | carp_unique ( | 
| 1010 |  |  |  |  |  |  | "You requested 'quote_names' but your storage class ($s_class) does " | 
| 1011 |  |  |  |  |  |  | . 'not explicitly define a default sql_quote_char and you have not ' | 
| 1012 |  |  |  |  |  |  | . 'supplied a quote_char as part of your connection_info. DBIC will ' | 
| 1013 |  |  |  |  |  |  | .q{default to the ANSI SQL standard quote '"', which works most of } | 
| 1014 |  |  |  |  |  |  | . "the time. Please file an RT ticket against '$s_class'." | 
| 1015 |  |  |  |  |  |  | ); | 
| 1016 |  |  |  |  |  |  |  | 
| 1017 |  |  |  |  |  |  | '"'; # RV | 
| 1018 |  |  |  |  |  |  | }; | 
| 1019 |  |  |  |  |  |  |  | 
| 1020 |  |  |  |  |  |  | $name_sep = (delete $opts{name_sep}) || $self->sql_name_sep; | 
| 1021 |  |  |  |  |  |  | } | 
| 1022 |  |  |  |  |  |  |  | 
| 1023 |  |  |  |  |  |  | $self->_sql_maker($sql_maker_class->new( | 
| 1024 |  |  |  |  |  |  | bindtype=>'columns', | 
| 1025 |  |  |  |  |  |  | array_datatypes => 1, | 
| 1026 |  |  |  |  |  |  | limit_dialect => $dialect, | 
| 1027 |  |  |  |  |  |  | ($quote_char ? (quote_char => $quote_char) : ()), | 
| 1028 |  |  |  |  |  |  | name_sep => ($name_sep || '.'), | 
| 1029 |  |  |  |  |  |  | %opts, | 
| 1030 |  |  |  |  |  |  | )); | 
| 1031 |  |  |  |  |  |  | } | 
| 1032 |  |  |  |  |  |  | return $self->_sql_maker; | 
| 1033 |  |  |  |  |  |  | } | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  | # nothing to do by default | 
| 1036 |  |  |  | 423 |  |  | sub _rebless {} | 
| 1037 |  |  |  | 437 |  |  | sub _init {} | 
| 1038 |  |  |  |  |  |  |  | 
| 1039 |  |  |  |  |  |  | sub _populate_dbh { | 
| 1040 |  |  |  |  |  |  |  | 
| 1041 | 649 |  |  | 649 |  | 32602 | $_[0]->_dbh(undef); # in case ->connected failed we might get sent here | 
| 1042 |  |  |  |  |  |  |  | 
| 1043 | 649 |  |  |  |  | 3327 | $_[0]->_dbh_details({}); # reset everything we know | 
| 1044 |  |  |  |  |  |  |  | 
| 1045 |  |  |  |  |  |  | # FIXME - this needs reenabling with the proper "no reset on same DSN" check | 
| 1046 |  |  |  |  |  |  | #$_[0]->_sql_maker(undef); # this may also end up being different | 
| 1047 |  |  |  |  |  |  |  | 
| 1048 | 649 |  |  |  |  | 2802 | $_[0]->_dbh($_[0]->_connect); | 
| 1049 |  |  |  |  |  |  |  | 
| 1050 | 466 |  |  |  |  | 2356 | $_[0]->_conn_pid($$) unless DBIx::Class::_ENV_::BROKEN_FORK; # on win32 these are in fact threads | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 | 466 |  |  |  |  | 2965 | $_[0]->_determine_driver; | 
| 1053 |  |  |  |  |  |  |  | 
| 1054 |  |  |  |  |  |  | # Always set the transaction depth on connect, since | 
| 1055 |  |  |  |  |  |  | #  there is no transaction in progress by definition | 
| 1056 | 465 | 100 |  |  |  | 4809 | $_[0]->{transaction_depth} = $_[0]->_dbh_autocommit ? 0 : 1; | 
| 1057 |  |  |  |  |  |  |  | 
| 1058 | 465 | 100 |  |  |  | 3090 | $_[0]->_run_connection_actions unless $_[0]->{_in_determine_driver}; | 
| 1059 |  |  |  |  |  |  |  | 
| 1060 | 452 |  |  |  |  | 3186 | $_[0]->_dbh; | 
| 1061 |  |  |  |  |  |  | } | 
| 1062 |  |  |  |  |  |  |  | 
| 1063 |  |  |  |  |  |  | sub _run_connection_actions { | 
| 1064 |  |  |  |  |  |  |  | 
| 1065 | 468 |  | 66 | 468 |  | 4737 | $_[0]->_do_connection_actions(connect_call_ => $_) for ( | 
| 1066 |  |  |  |  |  |  | ( $_[0]->on_connect_call || () ), | 
| 1067 |  |  |  |  |  |  | $_[0]->_parse_connect_do ('on_connect_do'), | 
| 1068 |  |  |  |  |  |  | ); | 
| 1069 |  |  |  |  |  |  | } | 
| 1070 |  |  |  |  |  |  |  | 
| 1071 |  |  |  |  |  |  |  | 
| 1072 |  |  |  |  |  |  |  | 
| 1073 |  |  |  |  |  |  | sub set_use_dbms_capability { | 
| 1074 | 280 |  |  | 280 | 0 | 6249 | $_[0]->set_inherited ($_[1], $_[2]); | 
| 1075 |  |  |  |  |  |  | } | 
| 1076 |  |  |  |  |  |  |  | 
| 1077 |  |  |  |  |  |  | sub get_use_dbms_capability { | 
| 1078 |  |  |  |  |  |  | my ($self, $capname) = @_; | 
| 1079 |  |  |  |  |  |  |  | 
| 1080 |  |  |  |  |  |  | my $use = $self->get_inherited ($capname); | 
| 1081 |  |  |  |  |  |  | return defined $use | 
| 1082 |  |  |  |  |  |  | ? $use | 
| 1083 |  |  |  |  |  |  | : do { $capname =~ s/^_use_/_supports_/; $self->get_dbms_capability ($capname) } | 
| 1084 |  |  |  |  |  |  | ; | 
| 1085 |  |  |  |  |  |  | } | 
| 1086 |  |  |  |  |  |  |  | 
| 1087 |  |  |  |  |  |  | sub set_dbms_capability { | 
| 1088 | 170 |  |  | 170 | 0 | 861 | $_[0]->_dbh_details->{capability}{$_[1]} = $_[2]; | 
| 1089 |  |  |  |  |  |  | } | 
| 1090 |  |  |  |  |  |  |  | 
| 1091 |  |  |  |  |  |  | sub get_dbms_capability { | 
| 1092 |  |  |  |  |  |  | my ($self, $capname) = @_; | 
| 1093 |  |  |  |  |  |  |  | 
| 1094 |  |  |  |  |  |  | my $cap = $self->_dbh_details->{capability}{$capname}; | 
| 1095 |  |  |  |  |  |  |  | 
| 1096 |  |  |  |  |  |  | unless (defined $cap) { | 
| 1097 |  |  |  |  |  |  | if (my $meth = $self->can ("_determine$capname")) { | 
| 1098 |  |  |  |  |  |  | $cap = $self->$meth ? 1 : 0; | 
| 1099 |  |  |  |  |  |  | } | 
| 1100 |  |  |  |  |  |  | else { | 
| 1101 |  |  |  |  |  |  | $cap = 0; | 
| 1102 |  |  |  |  |  |  | } | 
| 1103 |  |  |  |  |  |  |  | 
| 1104 |  |  |  |  |  |  | $self->set_dbms_capability ($capname, $cap); | 
| 1105 |  |  |  |  |  |  | } | 
| 1106 |  |  |  |  |  |  |  | 
| 1107 |  |  |  |  |  |  | return $cap; | 
| 1108 |  |  |  |  |  |  | } | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 |  |  |  |  |  |  | sub _server_info { | 
| 1111 |  |  |  |  |  |  | my $self = shift; | 
| 1112 |  |  |  |  |  |  |  | 
| 1113 |  |  |  |  |  |  | my $info; | 
| 1114 |  |  |  |  |  |  | unless ($info = $self->_dbh_details->{info}) { | 
| 1115 |  |  |  |  |  |  |  | 
| 1116 |  |  |  |  |  |  | $info = {}; | 
| 1117 |  |  |  |  |  |  | # this guarantees that problematic conninfo won't be hidden | 
| 1118 |  |  |  |  |  |  | # by the try{} below | 
| 1119 |  |  |  |  |  |  | $self->ensure_connected; | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  | my $server_version = try { | 
| 1122 |  |  |  |  |  |  | $self->_get_server_version | 
| 1123 |  |  |  |  |  |  | } catch { | 
| 1124 |  |  |  |  |  |  | # driver determination *may* use this codepath | 
| 1125 |  |  |  |  |  |  | # in which case we must rethrow | 
| 1126 |  |  |  |  |  |  | $self->throw_exception($_) if $self->{_in_determine_driver}; | 
| 1127 |  |  |  |  |  |  |  | 
| 1128 |  |  |  |  |  |  | # $server_version on failure | 
| 1129 |  |  |  |  |  |  | undef; | 
| 1130 |  |  |  |  |  |  | }; | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 |  |  |  |  |  |  | if (defined $server_version) { | 
| 1133 |  |  |  |  |  |  | $info->{dbms_version} = $server_version; | 
| 1134 |  |  |  |  |  |  |  | 
| 1135 |  |  |  |  |  |  | my ($numeric_version) = $server_version =~ /^([\d\.]+)/; | 
| 1136 |  |  |  |  |  |  | my @verparts = split (/\./, $numeric_version); | 
| 1137 |  |  |  |  |  |  | if ( | 
| 1138 |  |  |  |  |  |  | @verparts | 
| 1139 |  |  |  |  |  |  | && | 
| 1140 |  |  |  |  |  |  | $verparts[0] <= 999 | 
| 1141 |  |  |  |  |  |  | ) { | 
| 1142 |  |  |  |  |  |  | # consider only up to 3 version parts, iff not more than 3 digits | 
| 1143 |  |  |  |  |  |  | my @use_parts; | 
| 1144 |  |  |  |  |  |  | while (@verparts && @use_parts < 3) { | 
| 1145 |  |  |  |  |  |  | my $p = shift @verparts; | 
| 1146 |  |  |  |  |  |  | last if $p > 999; | 
| 1147 |  |  |  |  |  |  | push @use_parts, $p; | 
| 1148 |  |  |  |  |  |  | } | 
| 1149 |  |  |  |  |  |  | push @use_parts, 0 while @use_parts < 3; | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | $info->{normalized_dbms_version} = sprintf "%d.%03d%03d", @use_parts; | 
| 1152 |  |  |  |  |  |  | } | 
| 1153 |  |  |  |  |  |  | } | 
| 1154 |  |  |  |  |  |  |  | 
| 1155 |  |  |  |  |  |  | $self->_dbh_details->{info} = $info; | 
| 1156 |  |  |  |  |  |  | } | 
| 1157 |  |  |  |  |  |  |  | 
| 1158 |  |  |  |  |  |  | return $info; | 
| 1159 |  |  |  |  |  |  | } | 
| 1160 |  |  |  |  |  |  |  | 
| 1161 |  |  |  |  |  |  | sub _get_server_version { | 
| 1162 |  |  |  |  |  |  | shift->_dbh_get_info('SQL_DBMS_VER'); | 
| 1163 |  |  |  |  |  |  | } | 
| 1164 |  |  |  |  |  |  |  | 
| 1165 |  |  |  |  |  |  | sub _dbh_get_info { | 
| 1166 | 173 |  |  | 173 |  | 221 | my ($self, $info) = @_; | 
| 1167 |  |  |  |  |  |  |  | 
| 1168 | 173 | 50 |  |  |  | 581 | if ($info =~ /[^0-9]/) { | 
| 1169 | 173 |  |  |  |  | 2503 | require DBI::Const::GetInfoType; | 
| 1170 | 173 |  |  |  |  | 17782 | $info = $DBI::Const::GetInfoType::GetInfoType{$info}; | 
| 1171 | 173 | 50 |  |  |  | 310 | $self->throw_exception("Info type '$_[1]' not provided by DBI::Const::GetInfoType") | 
| 1172 |  |  |  |  |  |  | unless defined $info; | 
| 1173 |  |  |  |  |  |  | } | 
| 1174 |  |  |  |  |  |  |  | 
| 1175 | 173 |  |  |  |  | 317 | $self->_get_dbh->get_info($info); | 
| 1176 |  |  |  |  |  |  | } | 
| 1177 |  |  |  |  |  |  |  | 
| 1178 |  |  |  |  |  |  | sub _describe_connection { | 
| 1179 | 6 |  |  | 6 |  | 414 | require DBI::Const::GetInfoReturn; | 
| 1180 |  |  |  |  |  |  |  | 
| 1181 | 6 |  |  |  |  | 5806 | my $self = shift; | 
| 1182 |  |  |  |  |  |  |  | 
| 1183 | 6 |  |  |  |  | 7 | my $drv; | 
| 1184 |  |  |  |  |  |  | try { | 
| 1185 | 6 |  |  | 6 |  | 115 | $drv = $self->_extract_driver_from_connect_info; | 
| 1186 | 6 |  |  |  |  | 19 | $self->ensure_connected; | 
| 1187 | 6 |  |  |  |  | 37 | }; | 
| 1188 |  |  |  |  |  |  |  | 
| 1189 | 6 | 100 |  |  |  | 165 | $drv = "DBD::$drv" if $drv; | 
| 1190 |  |  |  |  |  |  |  | 
| 1191 |  |  |  |  |  |  | my $res = { | 
| 1192 |  |  |  |  |  |  | DBIC_DSN => $self->_dbi_connect_info->[0], | 
| 1193 |  |  |  |  |  |  | DBI_VER => DBI->VERSION, | 
| 1194 |  |  |  |  |  |  | DBIC_VER => DBIx::Class->VERSION, | 
| 1195 |  |  |  |  |  |  | DBIC_DRIVER => ref $self, | 
| 1196 |  |  |  |  |  |  | $drv ? ( | 
| 1197 |  |  |  |  |  |  | DBD => $drv, | 
| 1198 | 4 |  |  | 4 |  | 113 | DBD_VER => try { $drv->VERSION }, | 
| 1199 | 6 | 100 |  |  |  | 20 | ) : (), | 
| 1200 |  |  |  |  |  |  | }; | 
| 1201 |  |  |  |  |  |  |  | 
| 1202 |  |  |  |  |  |  | # try to grab data even if we never managed to connect | 
| 1203 |  |  |  |  |  |  | # will cover us in cases of an oddly broken half-connect | 
| 1204 | 6 |  |  |  |  | 85 | for my $inf ( | 
| 1205 |  |  |  |  |  |  | #keys %DBI::Const::GetInfoType::GetInfoType, | 
| 1206 |  |  |  |  |  |  | qw/ | 
| 1207 |  |  |  |  |  |  | SQL_CURSOR_COMMIT_BEHAVIOR | 
| 1208 |  |  |  |  |  |  | SQL_CURSOR_ROLLBACK_BEHAVIOR | 
| 1209 |  |  |  |  |  |  | SQL_CURSOR_SENSITIVITY | 
| 1210 |  |  |  |  |  |  | SQL_DATA_SOURCE_NAME | 
| 1211 |  |  |  |  |  |  | SQL_DBMS_NAME | 
| 1212 |  |  |  |  |  |  | SQL_DBMS_VER | 
| 1213 |  |  |  |  |  |  | SQL_DEFAULT_TXN_ISOLATION | 
| 1214 |  |  |  |  |  |  | SQL_DM_VER | 
| 1215 |  |  |  |  |  |  | SQL_DRIVER_NAME | 
| 1216 |  |  |  |  |  |  | SQL_DRIVER_ODBC_VER | 
| 1217 |  |  |  |  |  |  | SQL_DRIVER_VER | 
| 1218 |  |  |  |  |  |  | SQL_EXPRESSIONS_IN_ORDERBY | 
| 1219 |  |  |  |  |  |  | SQL_GROUP_BY | 
| 1220 |  |  |  |  |  |  | SQL_IDENTIFIER_CASE | 
| 1221 |  |  |  |  |  |  | SQL_IDENTIFIER_QUOTE_CHAR | 
| 1222 |  |  |  |  |  |  | SQL_MAX_CATALOG_NAME_LEN | 
| 1223 |  |  |  |  |  |  | SQL_MAX_COLUMN_NAME_LEN | 
| 1224 |  |  |  |  |  |  | SQL_MAX_IDENTIFIER_LEN | 
| 1225 |  |  |  |  |  |  | SQL_MAX_TABLE_NAME_LEN | 
| 1226 |  |  |  |  |  |  | SQL_MULTIPLE_ACTIVE_TXN | 
| 1227 |  |  |  |  |  |  | SQL_MULT_RESULT_SETS | 
| 1228 |  |  |  |  |  |  | SQL_NEED_LONG_DATA_LEN | 
| 1229 |  |  |  |  |  |  | SQL_NON_NULLABLE_COLUMNS | 
| 1230 |  |  |  |  |  |  | SQL_ODBC_VER | 
| 1231 |  |  |  |  |  |  | SQL_QUALIFIER_NAME_SEPARATOR | 
| 1232 |  |  |  |  |  |  | SQL_QUOTED_IDENTIFIER_CASE | 
| 1233 |  |  |  |  |  |  | SQL_TXN_CAPABLE | 
| 1234 |  |  |  |  |  |  | SQL_TXN_ISOLATION_OPTION | 
| 1235 |  |  |  |  |  |  | / | 
| 1236 |  |  |  |  |  |  | ) { | 
| 1237 |  |  |  |  |  |  | # some drivers barf on things they do not know about instead | 
| 1238 |  |  |  |  |  |  | # of returning undef | 
| 1239 | 168 |  |  | 168 |  | 699 | my $v = try { $self->_dbh_get_info($inf) }; | 
|  | 168 |  |  |  |  | 2872 |  | 
| 1240 | 168 | 50 |  |  |  | 3952 | next unless defined $v; | 
| 1241 |  |  |  |  |  |  |  | 
| 1242 |  |  |  |  |  |  | #my $key = sprintf( '%s(%s)', $inf, $DBI::Const::GetInfoType::GetInfoType{$inf} ); | 
| 1243 | 0 |  |  |  |  | 0 | my $expl = DBI::Const::GetInfoReturn::Explain($inf, $v); | 
| 1244 | 0 | 0 |  |  |  | 0 | $res->{$inf} = DBI::Const::GetInfoReturn::Format($inf, $v) . ( $expl ? " ($expl)" : '' ); | 
| 1245 |  |  |  |  |  |  | } | 
| 1246 |  |  |  |  |  |  |  | 
| 1247 | 6 |  |  |  |  | 36 | $res; | 
| 1248 |  |  |  |  |  |  | } | 
| 1249 |  |  |  |  |  |  |  | 
| 1250 |  |  |  |  |  |  | sub _determine_driver { | 
| 1251 | 504 |  |  | 504 |  | 1157 | my ($self) = @_; | 
| 1252 |  |  |  |  |  |  |  | 
| 1253 | 504 | 100 | 100 |  |  | 3549 | if ((not $self->_driver_determined) && (not $self->{_in_determine_driver})) { | 
| 1254 | 438 |  |  |  |  | 39519 | my $started_connected = 0; | 
| 1255 | 438 |  |  |  |  | 2131 | local $self->{_in_determine_driver} = 1; | 
| 1256 |  |  |  |  |  |  |  | 
| 1257 | 438 | 100 |  |  |  | 1773 | if (ref($self) eq __PACKAGE__) { | 
| 1258 | 429 |  |  |  |  | 755 | my $driver; | 
| 1259 | 429 | 100 |  |  |  | 1785 | if ($self->_dbh) { # we are connected | 
| 1260 | 396 |  |  |  |  | 5615 | $driver = $self->_dbh->{Driver}{Name}; | 
| 1261 | 396 |  |  |  |  | 1100 | $started_connected = 1; | 
| 1262 |  |  |  |  |  |  | } | 
| 1263 |  |  |  |  |  |  | else { | 
| 1264 | 33 |  |  |  |  | 790 | $driver = $self->_extract_driver_from_connect_info; | 
| 1265 |  |  |  |  |  |  | } | 
| 1266 |  |  |  |  |  |  |  | 
| 1267 | 429 | 100 |  |  |  | 1261 | if ($driver) { | 
| 1268 | 427 |  |  |  |  | 1215 | my $storage_class = "DBIx::Class::Storage::DBI::${driver}"; | 
| 1269 | 427 | 100 |  |  |  | 3356 | if ($self->load_optional_class($storage_class)) { | 
| 1270 | 423 |  |  |  |  | 7077 | mro::set_mro($storage_class, 'c3'); | 
| 1271 | 423 |  |  |  |  | 895 | bless $self, $storage_class; | 
| 1272 | 423 |  |  |  |  | 2613 | $self->_rebless(); | 
| 1273 |  |  |  |  |  |  | } | 
| 1274 |  |  |  |  |  |  | else { | 
| 1275 | 4 |  |  |  |  | 41 | $self->_warn_undetermined_driver( | 
| 1276 |  |  |  |  |  |  | 'This version of DBIC does not yet seem to supply a driver for ' | 
| 1277 |  |  |  |  |  |  | . "your particular RDBMS and/or connection method ('$driver')." | 
| 1278 |  |  |  |  |  |  | ); | 
| 1279 |  |  |  |  |  |  | } | 
| 1280 |  |  |  |  |  |  | } | 
| 1281 |  |  |  |  |  |  | else { | 
| 1282 | 2 |  |  |  |  | 9 | $self->_warn_undetermined_driver( | 
| 1283 |  |  |  |  |  |  | 'Unable to extract a driver name from connect info - this ' | 
| 1284 |  |  |  |  |  |  | . 'should not have happened.' | 
| 1285 |  |  |  |  |  |  | ); | 
| 1286 |  |  |  |  |  |  | } | 
| 1287 |  |  |  |  |  |  | } | 
| 1288 |  |  |  |  |  |  |  | 
| 1289 | 438 |  |  |  |  | 2026 | $self->_driver_determined(1); | 
| 1290 |  |  |  |  |  |  |  | 
| 1291 | 438 |  |  |  |  | 675 | Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO; | 
| 1292 |  |  |  |  |  |  |  | 
| 1293 | 438 | 100 |  |  |  | 5476 | if ($self->can('source_bind_attributes')) { | 
| 1294 | 1 |  |  |  |  | 4 | $self->throw_exception( | 
| 1295 | 1 |  |  |  |  | 21 | "Your storage subclass @{[ ref $self ]} provides (or inherits) the method " | 
| 1296 |  |  |  |  |  |  | . 'source_bind_attributes() for which support has been removed as of Jan 2013. ' | 
| 1297 |  |  |  |  |  |  | . 'If you are not sure how to proceed please contact the development team via ' | 
| 1298 |  |  |  |  |  |  | . DBIx::Class::_ENV_::HELP_URL | 
| 1299 |  |  |  |  |  |  | ); | 
| 1300 |  |  |  |  |  |  | } | 
| 1301 |  |  |  |  |  |  |  | 
| 1302 | 437 |  |  |  |  | 1923 | $self->_init; # run driver-specific initializations | 
| 1303 |  |  |  |  |  |  |  | 
| 1304 | 437 | 100 | 100 |  |  | 2816 | $self->_run_connection_actions | 
| 1305 |  |  |  |  |  |  | if !$started_connected && defined $self->_dbh; | 
| 1306 |  |  |  |  |  |  | } | 
| 1307 |  |  |  |  |  |  | } | 
| 1308 |  |  |  |  |  |  |  | 
| 1309 |  |  |  |  |  |  | sub _extract_driver_from_connect_info { | 
| 1310 | 39 |  |  | 39 |  | 69 | my $self = shift; | 
| 1311 |  |  |  |  |  |  |  | 
| 1312 | 39 |  |  |  |  | 45 | my $drv; | 
| 1313 |  |  |  |  |  |  |  | 
| 1314 |  |  |  |  |  |  | # if connect_info is a CODEREF, we have no choice but to connect | 
| 1315 | 39 | 100 | 66 |  |  | 97 | if ( | 
| 1316 |  |  |  |  |  |  | ref $self->_dbi_connect_info->[0] | 
| 1317 |  |  |  |  |  |  | and | 
| 1318 |  |  |  |  |  |  | reftype $self->_dbi_connect_info->[0] eq 'CODE' | 
| 1319 |  |  |  |  |  |  | ) { | 
| 1320 | 3 |  |  |  |  | 11 | $self->_populate_dbh; | 
| 1321 | 3 |  |  |  |  | 31 | $drv = $self->_dbh->{Driver}{Name}; | 
| 1322 |  |  |  |  |  |  | } | 
| 1323 |  |  |  |  |  |  | else { | 
| 1324 |  |  |  |  |  |  | # try to use dsn to not require being connected, the driver may still | 
| 1325 |  |  |  |  |  |  | # force a connection later in _rebless to determine version | 
| 1326 |  |  |  |  |  |  | # (dsn may not be supplied at all if all we do is make a mock-schema) | 
| 1327 |  |  |  |  |  |  | # | 
| 1328 |  |  |  |  |  |  | # Use the same regex as the one used by DBI itself (even if the use of | 
| 1329 |  |  |  |  |  |  | # \w is odd given unicode): | 
| 1330 |  |  |  |  |  |  | # https://metacpan.org/source/TIMB/DBI-1.634/DBI.pm#L621 | 
| 1331 |  |  |  |  |  |  | # | 
| 1332 |  |  |  |  |  |  | # DO NOT use https://metacpan.org/source/TIMB/DBI-1.634/DBI.pm#L559-566 | 
| 1333 |  |  |  |  |  |  | # as there is a long-standing precedent of not loading DBI.pm until the | 
| 1334 |  |  |  |  |  |  | # very moment we are actually connecting | 
| 1335 |  |  |  |  |  |  | # | 
| 1336 | 36 |  | 50 |  |  | 89 | ($drv) = ($self->_dbi_connect_info->[0] || '') =~ /^dbi:(\w*)/i; | 
| 1337 | 36 |  | 100 |  |  | 126 | $drv ||= $ENV{DBI_DRIVER}; | 
| 1338 |  |  |  |  |  |  | } | 
| 1339 |  |  |  |  |  |  |  | 
| 1340 | 39 |  |  |  |  | 87 | return $drv; | 
| 1341 |  |  |  |  |  |  | } | 
| 1342 |  |  |  |  |  |  |  | 
| 1343 |  |  |  |  |  |  | sub _determine_connector_driver { | 
| 1344 | 0 |  |  | 0 |  | 0 | my ($self, $conn) = @_; | 
| 1345 |  |  |  |  |  |  |  | 
| 1346 | 0 |  |  |  |  | 0 | my $dbtype = $self->_dbh_get_info('SQL_DBMS_NAME'); | 
| 1347 |  |  |  |  |  |  |  | 
| 1348 | 0 | 0 |  |  |  | 0 | if (not $dbtype) { | 
| 1349 | 0 |  |  |  |  | 0 | $self->_warn_undetermined_driver( | 
| 1350 |  |  |  |  |  |  | 'Unable to retrieve RDBMS type (SQL_DBMS_NAME) of the engine behind your ' | 
| 1351 |  |  |  |  |  |  | . "$conn connector - this should not have happened." | 
| 1352 |  |  |  |  |  |  | ); | 
| 1353 | 0 |  |  |  |  | 0 | return; | 
| 1354 |  |  |  |  |  |  | } | 
| 1355 |  |  |  |  |  |  |  | 
| 1356 | 0 |  |  |  |  | 0 | $dbtype =~ s/\W/_/gi; | 
| 1357 |  |  |  |  |  |  |  | 
| 1358 | 0 |  |  |  |  | 0 | my $subclass = "DBIx::Class::Storage::DBI::${conn}::${dbtype}"; | 
| 1359 | 0 | 0 |  |  |  | 0 | return if $self->isa($subclass); | 
| 1360 |  |  |  |  |  |  |  | 
| 1361 | 0 | 0 |  |  |  | 0 | if ($self->load_optional_class($subclass)) { | 
| 1362 | 0 |  |  |  |  | 0 | bless $self, $subclass; | 
| 1363 | 0 |  |  |  |  | 0 | $self->_rebless; | 
| 1364 |  |  |  |  |  |  | } | 
| 1365 |  |  |  |  |  |  | else { | 
| 1366 | 0 |  |  |  |  | 0 | $self->_warn_undetermined_driver( | 
| 1367 |  |  |  |  |  |  | 'This version of DBIC does not yet seem to supply a driver for ' | 
| 1368 |  |  |  |  |  |  | . "your particular RDBMS and/or connection method ('$conn/$dbtype')." | 
| 1369 |  |  |  |  |  |  | ); | 
| 1370 |  |  |  |  |  |  | } | 
| 1371 |  |  |  |  |  |  | } | 
| 1372 |  |  |  |  |  |  |  | 
| 1373 |  |  |  |  |  |  | sub _warn_undetermined_driver { | 
| 1374 | 6 |  |  | 6 |  | 10 | my ($self, $msg) = @_; | 
| 1375 |  |  |  |  |  |  |  | 
| 1376 | 6 |  |  |  |  | 34 | require Data::Dumper::Concise; | 
| 1377 |  |  |  |  |  |  |  | 
| 1378 | 6 |  |  |  |  | 32 | carp_once ($msg . ' While we will attempt to continue anyway, the results ' | 
| 1379 |  |  |  |  |  |  | . 'are likely to be underwhelming. Please upgrade DBIC, and if this message ' | 
| 1380 |  |  |  |  |  |  | . "does not go away, file a bugreport including the following info:\n" | 
| 1381 |  |  |  |  |  |  | . Data::Dumper::Concise::Dumper($self->_describe_connection) | 
| 1382 |  |  |  |  |  |  | ); | 
| 1383 |  |  |  |  |  |  | } | 
| 1384 |  |  |  |  |  |  |  | 
| 1385 |  |  |  |  |  |  | sub _do_connection_actions { | 
| 1386 | 1836 |  |  | 1836 |  | 3396 | my ($self, $method_prefix, $call, @args) = @_; | 
| 1387 |  |  |  |  |  |  |  | 
| 1388 |  |  |  |  |  |  | try { | 
| 1389 | 1836 | 100 |  | 1836 |  | 79589 | if (not ref($call)) { | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 1390 | 25 |  |  |  |  | 49 | my $method = $method_prefix . $call; | 
| 1391 | 25 |  |  |  |  | 236 | $self->$method(@args); | 
| 1392 |  |  |  |  |  |  | } | 
| 1393 |  |  |  |  |  |  | elsif (ref($call) eq 'CODE') { | 
| 1394 | 900 |  |  |  |  | 3652 | $self->$call(@args); | 
| 1395 |  |  |  |  |  |  | } | 
| 1396 |  |  |  |  |  |  | elsif (ref($call) eq 'ARRAY') { | 
| 1397 | 911 | 100 |  |  |  | 2494 | if (ref($call->[0]) ne 'ARRAY') { | 
| 1398 | 447 |  |  |  |  | 1388 | $self->_do_connection_actions($method_prefix, $_) for @$call; | 
| 1399 |  |  |  |  |  |  | } | 
| 1400 |  |  |  |  |  |  | else { | 
| 1401 | 464 |  |  |  |  | 2683 | $self->_do_connection_actions($method_prefix, @$_) for @$call; | 
| 1402 |  |  |  |  |  |  | } | 
| 1403 |  |  |  |  |  |  | } | 
| 1404 |  |  |  |  |  |  | else { | 
| 1405 | 0 |  |  |  |  | 0 | $self->throw_exception (sprintf ("Don't know how to process conection actions of type '%s'", ref($call)) ); | 
| 1406 |  |  |  |  |  |  | } | 
| 1407 |  |  |  |  |  |  | } | 
| 1408 |  |  |  |  |  |  | catch { | 
| 1409 | 29 | 100 |  | 29 |  | 817 | if ( $method_prefix =~ /^connect/ ) { | 
| 1410 |  |  |  |  |  |  | # this is an on_connect cycle - we can't just throw while leaving | 
| 1411 |  |  |  |  |  |  | # a handle in an undefined state in our storage object | 
| 1412 |  |  |  |  |  |  | # kill it with fire and rethrow | 
| 1413 | 26 |  |  |  |  | 1166 | $self->_dbh(undef); | 
| 1414 | 26 |  |  |  |  | 129 | $self->throw_exception( $_[0] ); | 
| 1415 |  |  |  |  |  |  | } | 
| 1416 |  |  |  |  |  |  | else { | 
| 1417 | 3 |  |  |  |  | 18 | carp "Disconnect action failed: $_[0]"; | 
| 1418 |  |  |  |  |  |  | } | 
| 1419 | 1836 |  |  |  |  | 12252 | }; | 
| 1420 |  |  |  |  |  |  |  | 
| 1421 | 1810 |  |  |  |  | 215446 | return $self; | 
| 1422 |  |  |  |  |  |  | } | 
| 1423 |  |  |  |  |  |  |  | 
| 1424 |  |  |  |  |  |  | sub connect_call_do_sql { | 
| 1425 | 12 |  |  | 12 | 0 | 17 | my $self = shift; | 
| 1426 | 12 |  |  |  |  | 39 | $self->_do_query(@_); | 
| 1427 |  |  |  |  |  |  | } | 
| 1428 |  |  |  |  |  |  |  | 
| 1429 |  |  |  |  |  |  | sub disconnect_call_do_sql { | 
| 1430 | 4 |  |  | 4 | 0 | 7 | my $self = shift; | 
| 1431 | 4 |  |  |  |  | 13 | $self->_do_query(@_); | 
| 1432 |  |  |  |  |  |  | } | 
| 1433 |  |  |  |  |  |  |  | 
| 1434 |  |  |  |  |  |  | =head2 connect_call_datetime_setup | 
| 1435 |  |  |  |  |  |  |  | 
| 1436 |  |  |  |  |  |  | A no-op stub method, provided so that one can always safely supply the | 
| 1437 |  |  |  |  |  |  | L | 
| 1438 |  |  |  |  |  |  |  | 
| 1439 |  |  |  |  |  |  | on_connect_call => 'datetime_setup' | 
| 1440 |  |  |  |  |  |  |  | 
| 1441 |  |  |  |  |  |  | This way one does not need to know in advance whether the underlying | 
| 1442 |  |  |  |  |  |  | storage requires any sort of hand-holding when dealing with calendar | 
| 1443 |  |  |  |  |  |  | data. | 
| 1444 |  |  |  |  |  |  |  | 
| 1445 |  |  |  |  |  |  | =cut | 
| 1446 |  |  |  |  |  |  |  | 
| 1447 | 0 |  |  | 0 | 1 | 0 | sub connect_call_datetime_setup { 1 } | 
| 1448 |  |  |  |  |  |  |  | 
| 1449 |  |  |  |  |  |  | sub _do_query { | 
| 1450 | 20 |  |  | 20 |  | 65 | my ($self, $action) = @_; | 
| 1451 |  |  |  |  |  |  |  | 
| 1452 | 20 | 100 |  |  |  | 46 | if (ref $action eq 'CODE') { | 
| 1453 | 4 |  |  |  |  | 13 | $action = $action->($self); | 
| 1454 | 4 |  |  |  |  | 669 | $self->_do_query($_) foreach @$action; | 
| 1455 |  |  |  |  |  |  | } | 
| 1456 |  |  |  |  |  |  | else { | 
| 1457 |  |  |  |  |  |  | # Most debuggers expect ($sql, @bind), so we need to exclude | 
| 1458 |  |  |  |  |  |  | # the attribute hash which is the second argument to $dbh->do | 
| 1459 |  |  |  |  |  |  | # furthermore the bind values are usually to be presented | 
| 1460 |  |  |  |  |  |  | # as named arrayref pairs, so wrap those here too | 
| 1461 | 16 | 100 |  |  |  | 49 | my @do_args = (ref $action eq 'ARRAY') ? (@$action) : ($action); | 
| 1462 | 16 |  |  |  |  | 22 | my $sql = shift @do_args; | 
| 1463 | 16 |  |  |  |  | 20 | my $attrs = shift @do_args; | 
| 1464 | 16 |  |  |  |  | 28 | my @bind = map { [ undef, $_ ] } @do_args; | 
|  | 3 |  |  |  |  | 8 |  | 
| 1465 |  |  |  |  |  |  |  | 
| 1466 |  |  |  |  |  |  | $self->dbh_do(sub { | 
| 1467 | 16 |  |  | 16 |  | 75 | $_[0]->_query_start($sql, \@bind); | 
| 1468 | 16 |  |  |  |  | 698 | $_[1]->do($sql, $attrs, @do_args); | 
| 1469 | 11 |  |  |  |  | 1474 | $_[0]->_query_end($sql, \@bind); | 
| 1470 | 16 |  |  |  |  | 92 | }); | 
| 1471 |  |  |  |  |  |  | } | 
| 1472 |  |  |  |  |  |  |  | 
| 1473 | 15 |  |  |  |  | 268 | return $self; | 
| 1474 |  |  |  |  |  |  | } | 
| 1475 |  |  |  |  |  |  |  | 
| 1476 |  |  |  |  |  |  | sub _connect { | 
| 1477 | 649 |  |  | 649 |  | 1057 | my $self = shift; | 
| 1478 |  |  |  |  |  |  |  | 
| 1479 | 649 |  |  |  |  | 2168 | my $info = $self->_dbi_connect_info; | 
| 1480 |  |  |  |  |  |  |  | 
| 1481 | 649 | 100 |  |  |  | 1912 | $self->throw_exception("You did not provide any connection_info") | 
| 1482 |  |  |  |  |  |  | unless defined $info->[0]; | 
| 1483 |  |  |  |  |  |  |  | 
| 1484 | 646 |  |  |  |  | 838 | my ($old_connect_via, $dbh); | 
| 1485 |  |  |  |  |  |  |  | 
| 1486 | 646 | 0 | 33 |  |  | 2214 | local $DBI::connect_via = 'connect' if $INC{'Apache/DBI.pm'} && $ENV{MOD_PERL}; | 
| 1487 |  |  |  |  |  |  |  | 
| 1488 |  |  |  |  |  |  | # this odd anonymous coderef dereference is in fact really | 
| 1489 |  |  |  |  |  |  | # necessary to avoid the unwanted effect described in perl5 | 
| 1490 |  |  |  |  |  |  | # RT#75792 | 
| 1491 |  |  |  |  |  |  | # | 
| 1492 |  |  |  |  |  |  | # in addition the coderef itself can't reside inside the try{} block below | 
| 1493 |  |  |  |  |  |  | # as it somehow triggers a leak under perl -d | 
| 1494 |  |  |  |  |  |  | my $dbh_error_handler_installer = sub { | 
| 1495 | 466 |  |  | 466 |  | 1793 | weaken (my $weak_self = $_[0]); | 
| 1496 |  |  |  |  |  |  |  | 
| 1497 |  |  |  |  |  |  | # the coderef is blessed so we can distinguish it from externally | 
| 1498 |  |  |  |  |  |  | # supplied handles (which must be preserved) | 
| 1499 |  |  |  |  |  |  | $_[1]->{HandleError} = bless sub { | 
| 1500 | 44 | 100 |  |  |  | 3060 | if ($weak_self) { | 
| 1501 | 43 |  |  |  |  | 397 | $weak_self->throw_exception("DBI Exception: $_[0]"); | 
| 1502 |  |  |  |  |  |  | } | 
| 1503 |  |  |  |  |  |  | else { | 
| 1504 |  |  |  |  |  |  | # the handler may be invoked by something totally out of | 
| 1505 |  |  |  |  |  |  | # the scope of DBIC | 
| 1506 | 1 |  |  |  |  | 5 | DBIx::Class::Exception->throw("DBI Exception (unhandled by DBIC, ::Schema GCed): $_[0]"); | 
| 1507 |  |  |  |  |  |  | } | 
| 1508 | 466 |  |  |  |  | 6274 | }, '__DBIC__DBH__ERROR__HANDLER__'; | 
| 1509 | 646 |  |  |  |  | 2819 | }; | 
| 1510 |  |  |  |  |  |  |  | 
| 1511 |  |  |  |  |  |  | try { | 
| 1512 | 646 | 100 |  | 646 |  | 32328 | if(ref $info->[0] eq 'CODE') { | 
| 1513 | 5 |  |  |  |  | 22 | $dbh = $info->[0]->(); | 
| 1514 |  |  |  |  |  |  | } | 
| 1515 |  |  |  |  |  |  | else { | 
| 1516 | 641 |  |  |  |  | 290180 | require DBI; | 
| 1517 | 641 |  |  |  |  | 2956385 | $dbh = DBI->connect(@$info); | 
| 1518 |  |  |  |  |  |  | } | 
| 1519 |  |  |  |  |  |  |  | 
| 1520 | 466 | 50 |  |  |  | 1999968 | die $DBI::errstr unless $dbh; | 
| 1521 |  |  |  |  |  |  |  | 
| 1522 | 466 | 0 |  |  |  | 5153 | die sprintf ("%s fresh DBI handle with a *false* 'Active' attribute. " | 
|  |  | 50 |  |  |  |  |  | 
| 1523 |  |  |  |  |  |  | . 'This handle is disconnected as far as DBIC is concerned, and we can ' | 
| 1524 |  |  |  |  |  |  | . 'not continue', | 
| 1525 |  |  |  |  |  |  | ref $info->[0] eq 'CODE' | 
| 1526 |  |  |  |  |  |  | ? "Connection coderef $info->[0] returned a" | 
| 1527 |  |  |  |  |  |  | : 'DBI->connect($schema->storage->connect_info) resulted in a' | 
| 1528 |  |  |  |  |  |  | ) unless $dbh->FETCH('Active'); | 
| 1529 |  |  |  |  |  |  |  | 
| 1530 |  |  |  |  |  |  | # sanity checks unless asked otherwise | 
| 1531 | 466 | 50 |  |  |  | 3475 | unless ($self->unsafe) { | 
| 1532 |  |  |  |  |  |  |  | 
| 1533 |  |  |  |  |  |  | $self->throw_exception( | 
| 1534 |  |  |  |  |  |  | 'Refusing clobbering of {HandleError} installed on externally supplied ' | 
| 1535 |  |  |  |  |  |  | ."DBI handle $dbh. Either remove the handler or use the 'unsafe' attribute." | 
| 1536 | 466 | 50 | 66 |  |  | 55285 | ) if $dbh->{HandleError} and ref $dbh->{HandleError} ne '__DBIC__DBH__ERROR__HANDLER__'; | 
| 1537 |  |  |  |  |  |  |  | 
| 1538 |  |  |  |  |  |  | # Default via _default_dbi_connect_attributes is 1, hence it was an explicit | 
| 1539 |  |  |  |  |  |  | # request, or an external handle. Complain and set anyway | 
| 1540 | 466 | 100 |  |  |  | 2930 | unless ($dbh->{RaiseError}) { | 
| 1541 | 2 | 50 |  |  |  | 19 | carp( ref $info->[0] eq 'CODE' | 
| 1542 |  |  |  |  |  |  |  | 
| 1543 |  |  |  |  |  |  | ? "The 'RaiseError' of the externally supplied DBI handle is set to false. " | 
| 1544 |  |  |  |  |  |  | ."DBIx::Class will toggle it back to true, unless the 'unsafe' connect " | 
| 1545 |  |  |  |  |  |  | .'attribute has been supplied' | 
| 1546 |  |  |  |  |  |  |  | 
| 1547 |  |  |  |  |  |  | : 'RaiseError => 0 supplied in your connection_info, without an explicit ' | 
| 1548 |  |  |  |  |  |  | .'unsafe => 1. Toggling RaiseError back to true' | 
| 1549 |  |  |  |  |  |  | ); | 
| 1550 |  |  |  |  |  |  |  | 
| 1551 | 2 |  |  |  |  | 167 | $dbh->{RaiseError} = 1; | 
| 1552 |  |  |  |  |  |  | } | 
| 1553 |  |  |  |  |  |  |  | 
| 1554 | 466 |  |  |  |  | 1857 | $dbh_error_handler_installer->($self, $dbh); | 
| 1555 |  |  |  |  |  |  | } | 
| 1556 |  |  |  |  |  |  | } | 
| 1557 |  |  |  |  |  |  | catch { | 
| 1558 | 180 |  |  | 180 |  | 125801 | $self->throw_exception("DBI Connection failed: $_") | 
| 1559 | 646 |  |  |  |  | 6335 | }; | 
| 1560 |  |  |  |  |  |  |  | 
| 1561 | 466 |  |  |  |  | 14613 | $self->_dbh_autocommit($dbh->{AutoCommit}); | 
| 1562 | 466 |  |  |  |  | 34055 | return $dbh; | 
| 1563 |  |  |  |  |  |  | } | 
| 1564 |  |  |  |  |  |  |  | 
| 1565 |  |  |  |  |  |  | sub txn_begin { | 
| 1566 |  |  |  |  |  |  | # this means we have not yet connected and do not know the AC status | 
| 1567 |  |  |  |  |  |  | # (e.g. coderef $dbh), need a full-fledged connection check | 
| 1568 |  |  |  |  |  |  | if (! defined $_[0]->_dbh_autocommit) { | 
| 1569 |  |  |  |  |  |  | $_[0]->ensure_connected; | 
| 1570 |  |  |  |  |  |  | } | 
| 1571 |  |  |  |  |  |  | # Otherwise simply connect or re-connect on pid changes | 
| 1572 |  |  |  |  |  |  | else { | 
| 1573 |  |  |  |  |  |  | $_[0]->_get_dbh; | 
| 1574 |  |  |  |  |  |  | } | 
| 1575 |  |  |  |  |  |  |  | 
| 1576 |  |  |  |  |  |  | shift->next::method(@_); | 
| 1577 |  |  |  |  |  |  | } | 
| 1578 |  |  |  |  |  |  |  | 
| 1579 |  |  |  |  |  |  | sub _exec_txn_begin { | 
| 1580 | 8693 |  |  | 8693 |  | 10045 | my $self = shift; | 
| 1581 |  |  |  |  |  |  |  | 
| 1582 |  |  |  |  |  |  | # if the user is utilizing txn_do - good for him, otherwise we need to | 
| 1583 |  |  |  |  |  |  | # ensure that the $dbh is healthy on BEGIN. | 
| 1584 |  |  |  |  |  |  | # We do this via ->dbh_do instead of ->dbh, so that the ->dbh "ping" | 
| 1585 |  |  |  |  |  |  | # will be replaced by a failure of begin_work itself (which will be | 
| 1586 |  |  |  |  |  |  | # then retried on reconnect) | 
| 1587 | 8693 | 100 |  |  |  | 18321 | if ($self->{_in_do_block}) { | 
| 1588 | 293 |  |  |  |  | 2971 | $self->_dbh->begin_work; | 
| 1589 |  |  |  |  |  |  | } else { | 
| 1590 | 8400 |  |  | 8400 |  | 32741 | $self->dbh_do(sub { $_[1]->begin_work }); | 
|  | 8400 |  |  |  |  | 46621 |  | 
| 1591 |  |  |  |  |  |  | } | 
| 1592 |  |  |  |  |  |  | } | 
| 1593 |  |  |  |  |  |  |  | 
| 1594 |  |  |  |  |  |  | sub txn_commit { | 
| 1595 | 9127 |  |  | 9127 | 1 | 9046 | my $self = shift; | 
| 1596 |  |  |  |  |  |  |  | 
| 1597 | 9127 | 50 |  |  |  | 17787 | $self->throw_exception("Unable to txn_commit() on a disconnected storage") | 
| 1598 |  |  |  |  |  |  | unless $self->_seems_connected; | 
| 1599 |  |  |  |  |  |  |  | 
| 1600 |  |  |  |  |  |  | # esoteric case for folks using external $dbh handles | 
| 1601 | 9127 | 0 | 33 |  |  | 23771 | if (! $self->transaction_depth and ! $self->_dbh->FETCH('AutoCommit') ) { | 
| 1602 | 0 |  |  |  |  | 0 | carp "Storage transaction_depth 0 does not match " | 
| 1603 |  |  |  |  |  |  | ."false AutoCommit of $self->{_dbh}, attempting COMMIT anyway"; | 
| 1604 | 0 |  |  |  |  | 0 | $self->transaction_depth(1); | 
| 1605 |  |  |  |  |  |  | } | 
| 1606 |  |  |  |  |  |  |  | 
| 1607 | 9127 |  |  |  |  | 28152 | $self->next::method(@_); | 
| 1608 |  |  |  |  |  |  |  | 
| 1609 |  |  |  |  |  |  | # if AutoCommit is disabled txn_depth never goes to 0 | 
| 1610 |  |  |  |  |  |  | # as a new txn is started immediately on commit | 
| 1611 | 9127 | 50 | 66 |  |  | 99536 | $self->transaction_depth(1) if ( | 
|  |  |  | 66 |  |  |  |  | 
| 1612 |  |  |  |  |  |  | !$self->transaction_depth | 
| 1613 |  |  |  |  |  |  | and | 
| 1614 |  |  |  |  |  |  | defined $self->_dbh_autocommit | 
| 1615 |  |  |  |  |  |  | and | 
| 1616 |  |  |  |  |  |  | ! $self->_dbh_autocommit | 
| 1617 |  |  |  |  |  |  | ); | 
| 1618 |  |  |  |  |  |  | } | 
| 1619 |  |  |  |  |  |  |  | 
| 1620 |  |  |  |  |  |  | sub _exec_txn_commit { | 
| 1621 | 8527 |  |  | 8527 |  | 320430 | shift->_dbh->commit; | 
| 1622 |  |  |  |  |  |  | } | 
| 1623 |  |  |  |  |  |  |  | 
| 1624 |  |  |  |  |  |  | sub txn_rollback { | 
| 1625 | 244 |  |  | 244 | 1 | 631 | my $self = shift; | 
| 1626 |  |  |  |  |  |  |  | 
| 1627 | 244 | 50 |  |  |  | 690 | $self->throw_exception("Unable to txn_rollback() on a disconnected storage") | 
| 1628 |  |  |  |  |  |  | unless $self->_seems_connected; | 
| 1629 |  |  |  |  |  |  |  | 
| 1630 |  |  |  |  |  |  | # esoteric case for folks using external $dbh handles | 
| 1631 | 244 | 0 | 33 |  |  | 1023 | if (! $self->transaction_depth and ! $self->_dbh->FETCH('AutoCommit') ) { | 
| 1632 | 0 |  |  |  |  | 0 | carp "Storage transaction_depth 0 does not match " | 
| 1633 |  |  |  |  |  |  | ."false AutoCommit of $self->{_dbh}, attempting ROLLBACK anyway"; | 
| 1634 | 0 |  |  |  |  | 0 | $self->transaction_depth(1); | 
| 1635 |  |  |  |  |  |  | } | 
| 1636 |  |  |  |  |  |  |  | 
| 1637 | 244 |  |  |  |  | 1108 | $self->next::method(@_); | 
| 1638 |  |  |  |  |  |  |  | 
| 1639 |  |  |  |  |  |  | # if AutoCommit is disabled txn_depth never goes to 0 | 
| 1640 |  |  |  |  |  |  | # as a new txn is started immediately on commit | 
| 1641 | 132 | 50 | 66 |  |  | 1956 | $self->transaction_depth(1) if ( | 
|  |  |  | 66 |  |  |  |  | 
| 1642 |  |  |  |  |  |  | !$self->transaction_depth | 
| 1643 |  |  |  |  |  |  | and | 
| 1644 |  |  |  |  |  |  | defined $self->_dbh_autocommit | 
| 1645 |  |  |  |  |  |  | and | 
| 1646 |  |  |  |  |  |  | ! $self->_dbh_autocommit | 
| 1647 |  |  |  |  |  |  | ); | 
| 1648 |  |  |  |  |  |  | } | 
| 1649 |  |  |  |  |  |  |  | 
| 1650 |  |  |  |  |  |  | sub _exec_txn_rollback { | 
| 1651 | 130 |  |  | 130 |  | 1929 | shift->_dbh->rollback; | 
| 1652 |  |  |  |  |  |  | } | 
| 1653 |  |  |  |  |  |  |  | 
| 1654 |  |  |  |  |  |  | # generate the DBI-specific stubs, which then fallback to ::Storage proper | 
| 1655 |  |  |  |  |  |  | quote_sub __PACKAGE__ . "::$_" => sprintf (<<'EOS', $_) for qw(svp_begin svp_release svp_rollback); | 
| 1656 |  |  |  |  |  |  | $_[0]->throw_exception('Unable to %s() on a disconnected storage') | 
| 1657 |  |  |  |  |  |  | unless $_[0]->_seems_connected; | 
| 1658 |  |  |  |  |  |  | shift->next::method(@_); | 
| 1659 |  |  |  |  |  |  | EOS | 
| 1660 |  |  |  |  |  |  |  | 
| 1661 |  |  |  |  |  |  | # This used to be the top-half of _execute.  It was split out to make it | 
| 1662 |  |  |  |  |  |  | #  easier to override in NoBindVars without duping the rest.  It takes up | 
| 1663 |  |  |  |  |  |  | #  all of _execute's args, and emits $sql, @bind. | 
| 1664 |  |  |  |  |  |  | sub _prep_for_execute { | 
| 1665 |  |  |  |  |  |  | #my ($self, $op, $ident, $args) = @_; | 
| 1666 | 17730 |  |  | 17730 |  | 38550 | return shift->_gen_sql_bind(@_) | 
| 1667 |  |  |  |  |  |  | } | 
| 1668 |  |  |  |  |  |  |  | 
| 1669 |  |  |  |  |  |  | sub _gen_sql_bind { | 
| 1670 | 18478 |  |  | 18478 |  | 24272 | my ($self, $op, $ident, $args) = @_; | 
| 1671 |  |  |  |  |  |  |  | 
| 1672 | 18478 |  |  |  |  | 14703 | my ($colinfos, $from); | 
| 1673 | 18478 | 100 |  |  |  | 56035 | if ( blessed($ident) ) { | 
| 1674 | 10636 |  |  |  |  | 31994 | $from = $ident->from; | 
| 1675 | 10636 |  |  |  |  | 23757 | $colinfos = $ident->columns_info; | 
| 1676 |  |  |  |  |  |  | } | 
| 1677 |  |  |  |  |  |  |  | 
| 1678 | 18478 |  |  |  |  | 20555 | my ($sql, $bind); | 
| 1679 | 18478 |  | 66 |  |  | 364989 | ($sql, @$bind) = $self->sql_maker->$op( ($from || $ident), @$args ); | 
| 1680 |  |  |  |  |  |  |  | 
| 1681 |  |  |  |  |  |  | $bind = $self->_resolve_bindattrs( | 
| 1682 | 18474 | 100 |  |  |  | 401926 | $ident, [ @{$args->[2]{bind}||[]}, @$bind ], $colinfos | 
|  | 18474 |  |  |  |  | 99692 |  | 
| 1683 |  |  |  |  |  |  | ); | 
| 1684 |  |  |  |  |  |  |  | 
| 1685 | 18474 | 50 | 66 |  |  | 137520 | if ( | 
|  |  |  | 66 |  |  |  |  | 
| 1686 |  |  |  |  |  |  | ! $ENV{DBIC_DT_SEARCH_OK} | 
| 1687 |  |  |  |  |  |  | and | 
| 1688 |  |  |  |  |  |  | $op eq 'select' | 
| 1689 |  |  |  |  |  |  | and | 
| 1690 |  |  |  |  |  |  | first { | 
| 1691 | 13905 | 100 | 100 | 13905 |  | 47812 | length ref $_->[1] | 
| 1692 |  |  |  |  |  |  | and | 
| 1693 |  |  |  |  |  |  | blessed($_->[1]) | 
| 1694 |  |  |  |  |  |  | and | 
| 1695 |  |  |  |  |  |  | $_->[1]->isa('DateTime') | 
| 1696 |  |  |  |  |  |  | } @$bind | 
| 1697 |  |  |  |  |  |  | ) { | 
| 1698 | 0 |  |  |  |  | 0 | carp_unique 'DateTime objects passed to search() are not supported ' | 
| 1699 |  |  |  |  |  |  | . 'properly (InflateColumn::DateTime formats and settings are not ' | 
| 1700 |  |  |  |  |  |  | . 'respected.) See ".. format a DateTime object for searching?" in ' | 
| 1701 |  |  |  |  |  |  | . 'DBIx::Class::Manual::FAQ. To disable this warning for good ' | 
| 1702 |  |  |  |  |  |  | . 'set $ENV{DBIC_DT_SEARCH_OK} to true' | 
| 1703 |  |  |  |  |  |  | } | 
| 1704 |  |  |  |  |  |  |  | 
| 1705 | 18474 |  |  |  |  | 66809 | return( $sql, $bind ); | 
| 1706 |  |  |  |  |  |  | } | 
| 1707 |  |  |  |  |  |  |  | 
| 1708 |  |  |  |  |  |  | sub _resolve_bindattrs { | 
| 1709 | 18553 |  |  | 18553 |  | 24440 | my ($self, $ident, $bind, $colinfos) = @_; | 
| 1710 |  |  |  |  |  |  |  | 
| 1711 |  |  |  |  |  |  | my $resolve_bindinfo = sub { | 
| 1712 |  |  |  |  |  |  | #my $infohash = shift; | 
| 1713 |  |  |  |  |  |  |  | 
| 1714 | 40735 |  | 100 | 40735 |  | 65396 | $colinfos ||= { %{ $self->_resolve_column_info($ident) } }; | 
|  | 6486 |  |  |  |  | 23742 |  | 
| 1715 |  |  |  |  |  |  |  | 
| 1716 | 40735 |  |  |  |  | 41722 | my $ret; | 
| 1717 | 40735 | 100 |  |  |  | 72408 | if (my $col = $_[0]->{dbic_colname}) { | 
| 1718 | 40726 |  |  |  |  | 30507 | $ret = { %{$_[0]} }; | 
|  | 40726 |  |  |  |  | 85800 |  | 
| 1719 |  |  |  |  |  |  |  | 
| 1720 |  |  |  |  |  |  | $ret->{sqlt_datatype} ||= $colinfos->{$col}{data_type} | 
| 1721 | 40726 | 100 | 33 |  |  | 169912 | if $colinfos->{$col}{data_type}; | 
| 1722 |  |  |  |  |  |  |  | 
| 1723 |  |  |  |  |  |  | $ret->{sqlt_size} ||= $colinfos->{$col}{size} | 
| 1724 | 40726 | 100 | 33 |  |  | 89981 | if $colinfos->{$col}{size}; | 
| 1725 |  |  |  |  |  |  | } | 
| 1726 |  |  |  |  |  |  |  | 
| 1727 | 40735 | 100 |  |  |  | 218892 | $ret || $_[0]; | 
| 1728 | 18553 |  |  |  |  | 66282 | }; | 
| 1729 |  |  |  |  |  |  |  | 
| 1730 |  |  |  |  |  |  | return [ map { | 
| 1731 | 18553 |  |  |  |  | 30873 | ( ref $_ ne 'ARRAY' or @$_ != 2 ) ? [ {}, $_ ] | 
| 1732 |  |  |  |  |  |  | : ( ! defined $_->[0] )             ? [ {}, $_->[1] ] | 
| 1733 |  |  |  |  |  |  | : (ref $_->[0] eq 'HASH')           ? [( | 
| 1734 |  |  |  |  |  |  | ! keys %{$_->[0]} | 
| 1735 |  |  |  |  |  |  | or | 
| 1736 |  |  |  |  |  |  | exists $_->[0]{dbd_attrs} | 
| 1737 |  |  |  |  |  |  | or | 
| 1738 |  |  |  |  |  |  | $_->[0]{sqlt_datatype} | 
| 1739 |  |  |  |  |  |  | ) ? $_->[0] | 
| 1740 |  |  |  |  |  |  | : $resolve_bindinfo->($_->[0]) | 
| 1741 |  |  |  |  |  |  | , $_->[1] | 
| 1742 |  |  |  |  |  |  | ] | 
| 1743 | 43397 | 100 | 100 |  |  | 254160 | : (ref $_->[0] eq 'SCALAR')         ? [ { sqlt_datatype => ${$_->[0]} }, $_->[1] ] | 
|  | 123 | 100 | 33 |  |  | 567 |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 1744 |  |  |  |  |  |  | :                                     [ $resolve_bindinfo->( | 
| 1745 |  |  |  |  |  |  | { dbic_colname => $_->[0] } | 
| 1746 |  |  |  |  |  |  | ), $_->[1] ] | 
| 1747 |  |  |  |  |  |  | } @$bind ]; | 
| 1748 |  |  |  |  |  |  | } | 
| 1749 |  |  |  |  |  |  |  | 
| 1750 |  |  |  |  |  |  | sub _format_for_trace { | 
| 1751 |  |  |  |  |  |  | #my ($self, $bind) = @_; | 
| 1752 |  |  |  |  |  |  |  | 
| 1753 |  |  |  |  |  |  | ### Turn @bind from something like this: | 
| 1754 |  |  |  |  |  |  | ###   ( [ "artist", 1 ], [ \%attrs, 3 ] ) | 
| 1755 |  |  |  |  |  |  | ### to this: | 
| 1756 |  |  |  |  |  |  | ###   ( "'1'", "'3'" ) | 
| 1757 |  |  |  |  |  |  |  | 
| 1758 |  |  |  |  |  |  | map { | 
| 1759 | 144 | 100 | 33 |  |  | 677 | defined( $_ && $_->[1] ) | 
| 1760 |  |  |  |  |  |  | ? qq{'$_->[1]'} | 
| 1761 |  |  |  |  |  |  | : q{NULL} | 
| 1762 | 141 | 50 |  | 141 |  | 143 | } @{$_[1] || []}; | 
|  | 141 |  |  |  |  | 358 |  | 
| 1763 |  |  |  |  |  |  | } | 
| 1764 |  |  |  |  |  |  |  | 
| 1765 |  |  |  |  |  |  | sub _query_start { | 
| 1766 | 17736 |  |  | 17736 |  | 22498 | my ( $self, $sql, $bind ) = @_; | 
| 1767 |  |  |  |  |  |  |  | 
| 1768 | 17736 | 100 |  |  |  | 49572 | $self->debugobj->query_start( $sql, $self->_format_for_trace($bind) ) | 
| 1769 |  |  |  |  |  |  | if $self->debug; | 
| 1770 |  |  |  |  |  |  | } | 
| 1771 |  |  |  |  |  |  |  | 
| 1772 |  |  |  |  |  |  | sub _query_end { | 
| 1773 | 17706 |  |  | 17706 |  | 23071 | my ( $self, $sql, $bind ) = @_; | 
| 1774 |  |  |  |  |  |  |  | 
| 1775 | 17706 | 100 |  |  |  | 52751 | $self->debugobj->query_end( $sql, $self->_format_for_trace($bind) ) | 
| 1776 |  |  |  |  |  |  | if $self->debug; | 
| 1777 |  |  |  |  |  |  | } | 
| 1778 |  |  |  |  |  |  |  | 
| 1779 |  |  |  |  |  |  | sub _dbi_attrs_for_bind { | 
| 1780 | 17716 |  |  | 17716 |  | 146388 | my ($self, $ident, $bind) = @_; | 
| 1781 |  |  |  |  |  |  |  | 
| 1782 | 17716 |  |  |  |  | 18240 | my @attrs; | 
| 1783 |  |  |  |  |  |  |  | 
| 1784 | 17716 |  |  |  |  | 27983 | for (map { $_->[0] } @$bind) { | 
|  | 41997 |  |  |  |  | 59974 |  | 
| 1785 | 41997 |  |  |  |  | 31230 | push @attrs, do { | 
| 1786 | 41997 | 50 |  |  |  | 78275 | if (exists $_->{dbd_attrs}) { | 
|  |  | 100 |  |  |  |  |  | 
| 1787 |  |  |  |  |  |  | $_->{dbd_attrs} | 
| 1788 | 0 |  |  |  |  | 0 | } | 
| 1789 |  |  |  |  |  |  | elsif($_->{sqlt_datatype}) { | 
| 1790 |  |  |  |  |  |  | # cache the result in the dbh_details hash, as it can not change unless | 
| 1791 |  |  |  |  |  |  | # we connect to something else | 
| 1792 | 41842 |  | 100 |  |  | 99191 | my $cache = $self->_dbh_details->{_datatype_map_cache} ||= {}; | 
| 1793 | 41842 | 100 |  |  |  | 75544 | if (not exists $cache->{$_->{sqlt_datatype}}) { | 
| 1794 | 2383 |  | 100 |  |  | 7120 | $cache->{$_->{sqlt_datatype}} = $self->bind_attribute_by_data_type($_->{sqlt_datatype}) || undef; | 
| 1795 |  |  |  |  |  |  | } | 
| 1796 | 41842 |  |  |  |  | 75718 | $cache->{$_->{sqlt_datatype}}; | 
| 1797 |  |  |  |  |  |  | } | 
| 1798 |  |  |  |  |  |  | else { | 
| 1799 | 155 |  |  |  |  | 272 | undef;  # always push something at this position | 
| 1800 |  |  |  |  |  |  | } | 
| 1801 |  |  |  |  |  |  | } | 
| 1802 |  |  |  |  |  |  | } | 
| 1803 |  |  |  |  |  |  |  | 
| 1804 | 17716 |  |  |  |  | 39517 | return \@attrs; | 
| 1805 |  |  |  |  |  |  | } | 
| 1806 |  |  |  |  |  |  |  | 
| 1807 |  |  |  |  |  |  | sub _execute { | 
| 1808 | 10079 |  |  | 10079 |  | 21495 | my ($self, $op, $ident, @args) = @_; | 
| 1809 |  |  |  |  |  |  |  | 
| 1810 | 10079 |  |  |  |  | 27029 | my ($sql, $bind) = $self->_prep_for_execute($op, $ident, \@args); | 
| 1811 |  |  |  |  |  |  |  | 
| 1812 |  |  |  |  |  |  | # not even a PID check - we do not care about the state of the _dbh. | 
| 1813 |  |  |  |  |  |  | # All we need is to get the appropriate drivers loaded if they aren't | 
| 1814 |  |  |  |  |  |  | # already so that the assumption in ad7c50fc26e holds | 
| 1815 | 10078 | 100 |  |  |  | 41571 | $self->_populate_dbh unless $self->_dbh; | 
| 1816 |  |  |  |  |  |  |  | 
| 1817 | 10072 |  |  |  |  | 36544 | $self->dbh_do( _dbh_execute =>     # retry over disconnects | 
| 1818 |  |  |  |  |  |  | $sql, | 
| 1819 |  |  |  |  |  |  | $bind, | 
| 1820 |  |  |  |  |  |  | $self->_dbi_attrs_for_bind($ident, $bind), | 
| 1821 |  |  |  |  |  |  | ); | 
| 1822 |  |  |  |  |  |  | } | 
| 1823 |  |  |  |  |  |  |  | 
| 1824 |  |  |  |  |  |  | sub _dbh_execute { | 
| 1825 | 10074 |  |  | 10074 |  | 85502 | my ($self, $dbh, $sql, $bind, $bind_attrs) = @_; | 
| 1826 |  |  |  |  |  |  |  | 
| 1827 | 10074 |  |  |  |  | 21871 | $self->_query_start( $sql, $bind ); | 
| 1828 |  |  |  |  |  |  |  | 
| 1829 | 10073 |  |  |  |  | 24104 | my $sth = $self->_bind_sth_params( | 
| 1830 |  |  |  |  |  |  | $self->_prepare_sth($dbh, $sql), | 
| 1831 |  |  |  |  |  |  | $bind, | 
| 1832 |  |  |  |  |  |  | $bind_attrs, | 
| 1833 |  |  |  |  |  |  | ); | 
| 1834 |  |  |  |  |  |  |  | 
| 1835 |  |  |  |  |  |  | # Can this fail without throwing an exception anyways??? | 
| 1836 | 10061 |  |  |  |  | 525198 | my $rv = $sth->execute(); | 
| 1837 | 10051 | 50 | 0 |  |  | 23086 | $self->throw_exception( | 
| 1838 |  |  |  |  |  |  | $sth->errstr || $sth->err || 'Unknown error: execute() returned false, but error flags were not set...' | 
| 1839 |  |  |  |  |  |  | ) if !$rv; | 
| 1840 |  |  |  |  |  |  |  | 
| 1841 | 10051 |  |  |  |  | 26976 | $self->_query_end( $sql, $bind ); | 
| 1842 |  |  |  |  |  |  |  | 
| 1843 | 10051 | 100 |  |  |  | 66141 | return (wantarray ? ($rv, $sth, @$bind) : $rv); | 
| 1844 |  |  |  |  |  |  | } | 
| 1845 |  |  |  |  |  |  |  | 
| 1846 |  |  |  |  |  |  | sub _prepare_sth { | 
| 1847 | 17722 |  |  | 17722 |  | 20428 | my ($self, $dbh, $sql) = @_; | 
| 1848 |  |  |  |  |  |  |  | 
| 1849 |  |  |  |  |  |  | # 3 is the if_active parameter which avoids active sth re-use | 
| 1850 | 17722 | 100 |  |  |  | 127237 | my $sth = $self->disable_sth_caching | 
| 1851 |  |  |  |  |  |  | ? $dbh->prepare($sql) | 
| 1852 |  |  |  |  |  |  | : $dbh->prepare_cached($sql, {}, 3); | 
| 1853 |  |  |  |  |  |  |  | 
| 1854 |  |  |  |  |  |  | # XXX You would think RaiseError would make this impossible, | 
| 1855 |  |  |  |  |  |  | #  but apparently that's not true :( | 
| 1856 |  |  |  |  |  |  | $self->throw_exception( | 
| 1857 |  |  |  |  |  |  | $dbh->errstr | 
| 1858 |  |  |  |  |  |  | || | 
| 1859 |  |  |  |  |  |  | sprintf( "\$dbh->prepare() of '%s' through %s failed *silently* without " | 
| 1860 |  |  |  |  |  |  | .'an exception and/or setting $dbh->errstr', | 
| 1861 |  |  |  |  |  |  | length ($sql) > 20 | 
| 1862 |  |  |  |  |  |  | ? substr($sql, 0, 20) . '...' | 
| 1863 |  |  |  |  |  |  | : $sql | 
| 1864 |  |  |  |  |  |  | , | 
| 1865 |  |  |  |  |  |  | 'DBD::' . $dbh->{Driver}{Name}, | 
| 1866 |  |  |  |  |  |  | ) | 
| 1867 | 17710 | 50 | 0 |  |  | 1115697 | ) if !$sth; | 
| 1868 |  |  |  |  |  |  |  | 
| 1869 | 17710 |  |  |  |  | 39360 | $sth; | 
| 1870 |  |  |  |  |  |  | } | 
| 1871 |  |  |  |  |  |  |  | 
| 1872 |  |  |  |  |  |  | sub _bind_sth_params { | 
| 1873 | 10061 |  |  | 10061 |  | 14917 | my ($self, $sth, $bind, $bind_attrs) = @_; | 
| 1874 |  |  |  |  |  |  |  | 
| 1875 | 10061 |  |  |  |  | 25058 | for my $i (0 .. $#$bind) { | 
| 1876 | 20074 | 50 |  |  |  | 35513 | if (ref $bind->[$i][1] eq 'SCALAR') {  # any scalarrefs are assumed to be bind_inouts | 
| 1877 |  |  |  |  |  |  | $sth->bind_param_inout( | 
| 1878 |  |  |  |  |  |  | $i + 1, # bind params counts are 1-based | 
| 1879 |  |  |  |  |  |  | $bind->[$i][1], | 
| 1880 | 0 |  | 0 |  |  | 0 | $bind->[$i][0]{dbd_size} || $self->_max_column_bytesize($bind->[$i][0]), # size | 
| 1881 |  |  |  |  |  |  | $bind_attrs->[$i], | 
| 1882 |  |  |  |  |  |  | ); | 
| 1883 |  |  |  |  |  |  | } | 
| 1884 |  |  |  |  |  |  | else { | 
| 1885 |  |  |  |  |  |  | # FIXME SUBOPTIMAL - DBI needs fixing to always stringify regardless of DBD | 
| 1886 | 20074 | 100 | 100 |  |  | 50499 | my $v = ( length ref $bind->[$i][1] and is_plain_value $bind->[$i][1] ) | 
| 1887 |  |  |  |  |  |  | ? "$bind->[$i][1]" | 
| 1888 |  |  |  |  |  |  | : $bind->[$i][1] | 
| 1889 |  |  |  |  |  |  | ; | 
| 1890 |  |  |  |  |  |  |  | 
| 1891 | 20074 |  |  |  |  | 95455 | $sth->bind_param( | 
| 1892 |  |  |  |  |  |  | $i + 1, | 
| 1893 |  |  |  |  |  |  | # The temp-var is CRUCIAL - DO NOT REMOVE IT, breaks older DBD::SQLite RT#79576 | 
| 1894 |  |  |  |  |  |  | $v, | 
| 1895 |  |  |  |  |  |  | $bind_attrs->[$i], | 
| 1896 |  |  |  |  |  |  | ); | 
| 1897 |  |  |  |  |  |  | } | 
| 1898 |  |  |  |  |  |  | } | 
| 1899 |  |  |  |  |  |  |  | 
| 1900 | 10061 |  |  |  |  | 14216 | $sth; | 
| 1901 |  |  |  |  |  |  | } | 
| 1902 |  |  |  |  |  |  |  | 
| 1903 |  |  |  |  |  |  | sub _prefetch_autovalues { | 
| 1904 | 1494 |  |  | 1494 |  | 2232 | my ($self, $source, $colinfo, $to_insert) = @_; | 
| 1905 |  |  |  |  |  |  |  | 
| 1906 | 1494 |  |  |  |  | 1568 | my %values; | 
| 1907 | 1494 |  |  |  |  | 4217 | for my $col (keys %$colinfo) { | 
| 1908 | 7604 | 0 | 0 |  |  | 13230 | if ( | 
|  |  |  | 33 |  |  |  |  | 
| 1909 |  |  |  |  |  |  | $colinfo->{$col}{auto_nextval} | 
| 1910 |  |  |  |  |  |  | and | 
| 1911 |  |  |  |  |  |  | ( | 
| 1912 |  |  |  |  |  |  | ! exists $to_insert->{$col} | 
| 1913 |  |  |  |  |  |  | or | 
| 1914 |  |  |  |  |  |  | is_literal_value($to_insert->{$col}) | 
| 1915 |  |  |  |  |  |  | ) | 
| 1916 |  |  |  |  |  |  | ) { | 
| 1917 |  |  |  |  |  |  | $values{$col} = $self->_sequence_fetch( | 
| 1918 |  |  |  |  |  |  | 'NEXTVAL', | 
| 1919 |  |  |  |  |  |  | ( $colinfo->{$col}{sequence} ||= | 
| 1920 | 0 |  | 0 |  |  | 0 | $self->_dbh_get_autoinc_seq($self->_get_dbh, $source, $col) | 
| 1921 |  |  |  |  |  |  | ), | 
| 1922 |  |  |  |  |  |  | ); | 
| 1923 |  |  |  |  |  |  | } | 
| 1924 |  |  |  |  |  |  | } | 
| 1925 |  |  |  |  |  |  |  | 
| 1926 | 1494 |  |  |  |  | 3132 | \%values; | 
| 1927 |  |  |  |  |  |  | } | 
| 1928 |  |  |  |  |  |  |  | 
| 1929 |  |  |  |  |  |  | sub insert { | 
| 1930 |  |  |  |  |  |  | my ($self, $source, $to_insert) = @_; | 
| 1931 |  |  |  |  |  |  |  | 
| 1932 |  |  |  |  |  |  | my $col_infos = $source->columns_info; | 
| 1933 |  |  |  |  |  |  |  | 
| 1934 |  |  |  |  |  |  | my $prefetched_values = $self->_prefetch_autovalues($source, $col_infos, $to_insert); | 
| 1935 |  |  |  |  |  |  |  | 
| 1936 |  |  |  |  |  |  | # fuse the values, but keep a separate list of prefetched_values so that | 
| 1937 |  |  |  |  |  |  | # they can be fused once again with the final return | 
| 1938 |  |  |  |  |  |  | $to_insert = { %$to_insert, %$prefetched_values }; | 
| 1939 |  |  |  |  |  |  |  | 
| 1940 |  |  |  |  |  |  | # FIXME - we seem to assume undef values as non-supplied. This is wrong. | 
| 1941 |  |  |  |  |  |  | # Investigate what does it take to s/defined/exists/ | 
| 1942 |  |  |  |  |  |  | my %pcols = map { $_ => 1 } $source->primary_columns; | 
| 1943 |  |  |  |  |  |  | my (%retrieve_cols, $autoinc_supplied, $retrieve_autoinc_col); | 
| 1944 |  |  |  |  |  |  | for my $col ($source->columns) { | 
| 1945 |  |  |  |  |  |  | if ($col_infos->{$col}{is_auto_increment}) { | 
| 1946 |  |  |  |  |  |  | $autoinc_supplied ||= 1 if defined $to_insert->{$col}; | 
| 1947 |  |  |  |  |  |  | $retrieve_autoinc_col ||= $col unless $autoinc_supplied; | 
| 1948 |  |  |  |  |  |  | } | 
| 1949 |  |  |  |  |  |  |  | 
| 1950 |  |  |  |  |  |  | # nothing to retrieve when explicit values are supplied | 
| 1951 |  |  |  |  |  |  | next if ( | 
| 1952 |  |  |  |  |  |  | defined $to_insert->{$col} and ! is_literal_value($to_insert->{$col}) | 
| 1953 |  |  |  |  |  |  | ); | 
| 1954 |  |  |  |  |  |  |  | 
| 1955 |  |  |  |  |  |  | # the 'scalar keys' is a trick to preserve the ->columns declaration order | 
| 1956 |  |  |  |  |  |  | $retrieve_cols{$col} = scalar keys %retrieve_cols if ( | 
| 1957 |  |  |  |  |  |  | $pcols{$col} | 
| 1958 |  |  |  |  |  |  | or | 
| 1959 |  |  |  |  |  |  | $col_infos->{$col}{retrieve_on_insert} | 
| 1960 |  |  |  |  |  |  | ); | 
| 1961 |  |  |  |  |  |  | }; | 
| 1962 |  |  |  |  |  |  |  | 
| 1963 |  |  |  |  |  |  | local $self->{_autoinc_supplied_for_op} = $autoinc_supplied; | 
| 1964 |  |  |  |  |  |  | local $self->{_perform_autoinc_retrieval} = $retrieve_autoinc_col; | 
| 1965 |  |  |  |  |  |  |  | 
| 1966 |  |  |  |  |  |  | my ($sqla_opts, @ir_container); | 
| 1967 |  |  |  |  |  |  | if (%retrieve_cols and $self->_use_insert_returning) { | 
| 1968 |  |  |  |  |  |  | $sqla_opts->{returning_container} = \@ir_container | 
| 1969 |  |  |  |  |  |  | if $self->_use_insert_returning_bound; | 
| 1970 |  |  |  |  |  |  |  | 
| 1971 |  |  |  |  |  |  | $sqla_opts->{returning} = [ | 
| 1972 |  |  |  |  |  |  | sort { $retrieve_cols{$a} <=> $retrieve_cols{$b} } keys %retrieve_cols | 
| 1973 |  |  |  |  |  |  | ]; | 
| 1974 |  |  |  |  |  |  | } | 
| 1975 |  |  |  |  |  |  |  | 
| 1976 |  |  |  |  |  |  | my ($rv, $sth) = $self->_execute('insert', $source, $to_insert, $sqla_opts); | 
| 1977 |  |  |  |  |  |  |  | 
| 1978 |  |  |  |  |  |  | my %returned_cols = %$to_insert; | 
| 1979 |  |  |  |  |  |  | if (my $retlist = $sqla_opts->{returning}) {  # if IR is supported - we will get everything in one set | 
| 1980 |  |  |  |  |  |  |  | 
| 1981 |  |  |  |  |  |  | unless( @ir_container ) { | 
| 1982 |  |  |  |  |  |  | try { | 
| 1983 |  |  |  |  |  |  |  | 
| 1984 |  |  |  |  |  |  | # FIXME - need to investigate why Caelum silenced this in 4d4dc518 | 
| 1985 |  |  |  |  |  |  | local $SIG{__WARN__} = sub {}; | 
| 1986 |  |  |  |  |  |  |  | 
| 1987 |  |  |  |  |  |  | @ir_container = $sth->fetchrow_array; | 
| 1988 |  |  |  |  |  |  | $sth->finish; | 
| 1989 |  |  |  |  |  |  |  | 
| 1990 |  |  |  |  |  |  | } catch { | 
| 1991 |  |  |  |  |  |  | # Evict the $sth from the cache in case we got here, since the finish() | 
| 1992 |  |  |  |  |  |  | # is crucial, at least on older Firebirds, possibly on other engines too | 
| 1993 |  |  |  |  |  |  | # | 
| 1994 |  |  |  |  |  |  | # It would be too complex to make this a proper subclass override, | 
| 1995 |  |  |  |  |  |  | # and besides we already take the try{} penalty, adding a catch that | 
| 1996 |  |  |  |  |  |  | # triggers infrequently is a no-brainer | 
| 1997 |  |  |  |  |  |  | # | 
| 1998 |  |  |  |  |  |  | if( my $kids = $self->_dbh->{CachedKids} ) { | 
| 1999 |  |  |  |  |  |  | $kids->{$_} == $sth and delete $kids->{$_} | 
| 2000 |  |  |  |  |  |  | for keys %$kids | 
| 2001 |  |  |  |  |  |  | } | 
| 2002 |  |  |  |  |  |  | }; | 
| 2003 |  |  |  |  |  |  | } | 
| 2004 |  |  |  |  |  |  |  | 
| 2005 |  |  |  |  |  |  | @returned_cols{@$retlist} = @ir_container if @ir_container; | 
| 2006 |  |  |  |  |  |  | } | 
| 2007 |  |  |  |  |  |  | else { | 
| 2008 |  |  |  |  |  |  | # pull in PK if needed and then everything else | 
| 2009 |  |  |  |  |  |  | if (my @missing_pri = grep { $pcols{$_} } keys %retrieve_cols) { | 
| 2010 |  |  |  |  |  |  |  | 
| 2011 |  |  |  |  |  |  | $self->throw_exception( "Missing primary key but Storage doesn't support last_insert_id" ) | 
| 2012 |  |  |  |  |  |  | unless $self->can('last_insert_id'); | 
| 2013 |  |  |  |  |  |  |  | 
| 2014 |  |  |  |  |  |  | my @pri_values = $self->last_insert_id($source, @missing_pri); | 
| 2015 |  |  |  |  |  |  |  | 
| 2016 |  |  |  |  |  |  | $self->throw_exception( "Can't get last insert id" ) | 
| 2017 |  |  |  |  |  |  | unless (@pri_values == @missing_pri); | 
| 2018 |  |  |  |  |  |  |  | 
| 2019 |  |  |  |  |  |  | @returned_cols{@missing_pri} = @pri_values; | 
| 2020 |  |  |  |  |  |  | delete @retrieve_cols{@missing_pri}; | 
| 2021 |  |  |  |  |  |  | } | 
| 2022 |  |  |  |  |  |  |  | 
| 2023 |  |  |  |  |  |  | # if there is more left to pull | 
| 2024 |  |  |  |  |  |  | if (%retrieve_cols) { | 
| 2025 |  |  |  |  |  |  | $self->throw_exception( | 
| 2026 |  |  |  |  |  |  | 'Unable to retrieve additional columns without a Primary Key on ' . $source->source_name | 
| 2027 |  |  |  |  |  |  | ) unless %pcols; | 
| 2028 |  |  |  |  |  |  |  | 
| 2029 |  |  |  |  |  |  | my @left_to_fetch = sort { $retrieve_cols{$a} <=> $retrieve_cols{$b} } keys %retrieve_cols; | 
| 2030 |  |  |  |  |  |  |  | 
| 2031 |  |  |  |  |  |  | my $cur = DBIx::Class::ResultSet->new($source, { | 
| 2032 |  |  |  |  |  |  | where => { map { $_ => $returned_cols{$_} } (keys %pcols) }, | 
| 2033 |  |  |  |  |  |  | select => \@left_to_fetch, | 
| 2034 |  |  |  |  |  |  | })->cursor; | 
| 2035 |  |  |  |  |  |  |  | 
| 2036 |  |  |  |  |  |  | @returned_cols{@left_to_fetch} = $cur->next; | 
| 2037 |  |  |  |  |  |  |  | 
| 2038 |  |  |  |  |  |  | $self->throw_exception('Duplicate row returned for PK-search after fresh insert') | 
| 2039 |  |  |  |  |  |  | if scalar $cur->next; | 
| 2040 |  |  |  |  |  |  | } | 
| 2041 |  |  |  |  |  |  | } | 
| 2042 |  |  |  |  |  |  |  | 
| 2043 |  |  |  |  |  |  | return { %$prefetched_values, %returned_cols }; | 
| 2044 |  |  |  |  |  |  | } | 
| 2045 |  |  |  |  |  |  |  | 
| 2046 |  |  |  |  |  |  | sub insert_bulk { | 
| 2047 | 0 |  |  | 0 | 0 | 0 | carp_unique( | 
| 2048 |  |  |  |  |  |  | 'insert_bulk() should have never been exposed as a public method and ' | 
| 2049 |  |  |  |  |  |  | . 'calling it is depecated as of Aug 2014. If you believe having a genuine ' | 
| 2050 |  |  |  |  |  |  | . 'use for this method please contact the development team via ' | 
| 2051 |  |  |  |  |  |  | . DBIx::Class::_ENV_::HELP_URL | 
| 2052 |  |  |  |  |  |  | ); | 
| 2053 |  |  |  |  |  |  |  | 
| 2054 | 0 | 0 |  |  |  | 0 | return '0E0' unless @{$_[3]||[]}; | 
|  | 0 | 0 |  |  |  | 0 |  | 
| 2055 |  |  |  |  |  |  |  | 
| 2056 | 0 |  |  |  |  | 0 | shift->_insert_bulk(@_); | 
| 2057 |  |  |  |  |  |  | } | 
| 2058 |  |  |  |  |  |  |  | 
| 2059 |  |  |  |  |  |  | sub _insert_bulk { | 
| 2060 |  |  |  |  |  |  | my ($self, $source, $cols, $data) = @_; | 
| 2061 |  |  |  |  |  |  |  | 
| 2062 |  |  |  |  |  |  | $self->throw_exception('Calling _insert_bulk without a dataset to process makes no sense') | 
| 2063 |  |  |  |  |  |  | unless @{$data||[]}; | 
| 2064 |  |  |  |  |  |  |  | 
| 2065 |  |  |  |  |  |  | my $colinfos = $source->columns_info($cols); | 
| 2066 |  |  |  |  |  |  |  | 
| 2067 |  |  |  |  |  |  | local $self->{_autoinc_supplied_for_op} = | 
| 2068 |  |  |  |  |  |  | (grep { $_->{is_auto_increment} } values %$colinfos) | 
| 2069 |  |  |  |  |  |  | ? 1 | 
| 2070 |  |  |  |  |  |  | : 0 | 
| 2071 |  |  |  |  |  |  | ; | 
| 2072 |  |  |  |  |  |  |  | 
| 2073 |  |  |  |  |  |  | # get a slice type index based on first row of data | 
| 2074 |  |  |  |  |  |  | # a "column" in this context may refer to more than one bind value | 
| 2075 |  |  |  |  |  |  | # e.g. \[ '?, ?', [...], [...] ] | 
| 2076 |  |  |  |  |  |  | # | 
| 2077 |  |  |  |  |  |  | # construct the value type index - a description of values types for every | 
| 2078 |  |  |  |  |  |  | # per-column slice of $data: | 
| 2079 |  |  |  |  |  |  | # | 
| 2080 |  |  |  |  |  |  | # nonexistent - nonbind literal | 
| 2081 |  |  |  |  |  |  | # 0 - regular value | 
| 2082 |  |  |  |  |  |  | # [] of bindattrs - resolved attribute(s) of bind(s) passed via literal+bind \[] combo | 
| 2083 |  |  |  |  |  |  | # | 
| 2084 |  |  |  |  |  |  | # also construct the column hash to pass to the SQL generator. For plain | 
| 2085 |  |  |  |  |  |  | # (non literal) values - convert the members of the first row into a | 
| 2086 |  |  |  |  |  |  | # literal+bind combo, with extra positional info in the bind attr hashref. | 
| 2087 |  |  |  |  |  |  | # This will allow us to match the order properly, and is so contrived | 
| 2088 |  |  |  |  |  |  | # because a user-supplied literal/bind (or something else specific to a | 
| 2089 |  |  |  |  |  |  | # resultsource and/or storage driver) can inject extra binds along the | 
| 2090 |  |  |  |  |  |  | # way, so one can't rely on "shift positions" ordering at all. Also we | 
| 2091 |  |  |  |  |  |  | # can't just hand SQLA a set of some known "values" (e.g. hashrefs that | 
| 2092 |  |  |  |  |  |  | # can be later matched up by address), because we want to supply a real | 
| 2093 |  |  |  |  |  |  | # value on which perhaps e.g. datatype checks will be performed | 
| 2094 |  |  |  |  |  |  | my ($proto_data, $serialized_bind_type_by_col_idx); | 
| 2095 |  |  |  |  |  |  | for my $col_idx (0..$#$cols) { | 
| 2096 |  |  |  |  |  |  | my $colname = $cols->[$col_idx]; | 
| 2097 |  |  |  |  |  |  | if (ref $data->[0][$col_idx] eq 'SCALAR') { | 
| 2098 |  |  |  |  |  |  | # no bind value at all - no type | 
| 2099 |  |  |  |  |  |  |  | 
| 2100 |  |  |  |  |  |  | $proto_data->{$colname} = $data->[0][$col_idx]; | 
| 2101 |  |  |  |  |  |  | } | 
| 2102 |  |  |  |  |  |  | elsif (ref $data->[0][$col_idx] eq 'REF' and ref ${$data->[0][$col_idx]} eq 'ARRAY' ) { | 
| 2103 |  |  |  |  |  |  | # repack, so we don't end up mangling the original \[] | 
| 2104 |  |  |  |  |  |  | my ($sql, @bind) = @${$data->[0][$col_idx]}; | 
| 2105 |  |  |  |  |  |  |  | 
| 2106 |  |  |  |  |  |  | # normalization of user supplied stuff | 
| 2107 |  |  |  |  |  |  | my $resolved_bind = $self->_resolve_bindattrs( | 
| 2108 |  |  |  |  |  |  | $source, \@bind, $colinfos, | 
| 2109 |  |  |  |  |  |  | ); | 
| 2110 |  |  |  |  |  |  |  | 
| 2111 |  |  |  |  |  |  | # store value-less (attrs only) bind info - we will be comparing all | 
| 2112 |  |  |  |  |  |  | # supplied binds against this for sanity | 
| 2113 |  |  |  |  |  |  | $serialized_bind_type_by_col_idx->{$col_idx} = serialize [ map { $_->[0] } @$resolved_bind ]; | 
| 2114 |  |  |  |  |  |  |  | 
| 2115 |  |  |  |  |  |  | $proto_data->{$colname} = \[ $sql, map { [ | 
| 2116 |  |  |  |  |  |  | # inject slice order to use for $proto_bind construction | 
| 2117 |  |  |  |  |  |  | { %{$resolved_bind->[$_][0]}, _bind_data_slice_idx => $col_idx, _literal_bind_subindex => $_+1 } | 
| 2118 |  |  |  |  |  |  | => | 
| 2119 |  |  |  |  |  |  | $resolved_bind->[$_][1] | 
| 2120 |  |  |  |  |  |  | ] } (0 .. $#bind) | 
| 2121 |  |  |  |  |  |  | ]; | 
| 2122 |  |  |  |  |  |  | } | 
| 2123 |  |  |  |  |  |  | else { | 
| 2124 |  |  |  |  |  |  | $serialized_bind_type_by_col_idx->{$col_idx} = undef; | 
| 2125 |  |  |  |  |  |  |  | 
| 2126 |  |  |  |  |  |  | $proto_data->{$colname} = \[ '?', [ | 
| 2127 |  |  |  |  |  |  | { dbic_colname => $colname, _bind_data_slice_idx => $col_idx } | 
| 2128 |  |  |  |  |  |  | => | 
| 2129 |  |  |  |  |  |  | $data->[0][$col_idx] | 
| 2130 |  |  |  |  |  |  | ] ]; | 
| 2131 |  |  |  |  |  |  | } | 
| 2132 |  |  |  |  |  |  | } | 
| 2133 |  |  |  |  |  |  |  | 
| 2134 |  |  |  |  |  |  | my ($sql, $proto_bind) = $self->_prep_for_execute ( | 
| 2135 |  |  |  |  |  |  | 'insert', | 
| 2136 |  |  |  |  |  |  | $source, | 
| 2137 |  |  |  |  |  |  | [ $proto_data ], | 
| 2138 |  |  |  |  |  |  | ); | 
| 2139 |  |  |  |  |  |  |  | 
| 2140 |  |  |  |  |  |  | if (! @$proto_bind and keys %$serialized_bind_type_by_col_idx) { | 
| 2141 |  |  |  |  |  |  | # if the bindlist is empty and we had some dynamic binds, this means the | 
| 2142 |  |  |  |  |  |  | # storage ate them away (e.g. the NoBindVars component) and interpolated | 
| 2143 |  |  |  |  |  |  | # them directly into the SQL. This obviously can't be good for multi-inserts | 
| 2144 |  |  |  |  |  |  | $self->throw_exception('Unable to invoke fast-path insert without storage placeholder support'); | 
| 2145 |  |  |  |  |  |  | } | 
| 2146 |  |  |  |  |  |  |  | 
| 2147 |  |  |  |  |  |  | # sanity checks | 
| 2148 |  |  |  |  |  |  | # FIXME - devise a flag "no babysitting" or somesuch to shut this off | 
| 2149 |  |  |  |  |  |  | # | 
| 2150 |  |  |  |  |  |  | # use an error reporting closure for convenience (less to pass) | 
| 2151 |  |  |  |  |  |  | my $bad_slice_report_cref = sub { | 
| 2152 |  |  |  |  |  |  | my ($msg, $r_idx, $c_idx) = @_; | 
| 2153 |  |  |  |  |  |  | $self->throw_exception(sprintf "%s for column '%s' in populate slice:\n%s", | 
| 2154 |  |  |  |  |  |  | $msg, | 
| 2155 |  |  |  |  |  |  | $cols->[$c_idx], | 
| 2156 |  |  |  |  |  |  | do { | 
| 2157 |  |  |  |  |  |  | require Data::Dumper::Concise; | 
| 2158 |  |  |  |  |  |  | local $Data::Dumper::Maxdepth = 5; | 
| 2159 |  |  |  |  |  |  | Data::Dumper::Concise::Dumper ({ | 
| 2160 |  |  |  |  |  |  | map { $cols->[$_] => | 
| 2161 |  |  |  |  |  |  | $data->[$r_idx][$_] | 
| 2162 |  |  |  |  |  |  | } 0..$#$cols | 
| 2163 |  |  |  |  |  |  | }), | 
| 2164 |  |  |  |  |  |  | } | 
| 2165 |  |  |  |  |  |  | ); | 
| 2166 |  |  |  |  |  |  | }; | 
| 2167 |  |  |  |  |  |  |  | 
| 2168 |  |  |  |  |  |  | for my $col_idx (0..$#$cols) { | 
| 2169 |  |  |  |  |  |  | my $reference_val = $data->[0][$col_idx]; | 
| 2170 |  |  |  |  |  |  |  | 
| 2171 |  |  |  |  |  |  | for my $row_idx (1..$#$data) {  # we are comparing against what we got from [0] above, hence start from 1 | 
| 2172 |  |  |  |  |  |  | my $val = $data->[$row_idx][$col_idx]; | 
| 2173 |  |  |  |  |  |  |  | 
| 2174 |  |  |  |  |  |  | if (! exists $serialized_bind_type_by_col_idx->{$col_idx}) { # literal no binds | 
| 2175 |  |  |  |  |  |  | if (ref $val ne 'SCALAR') { | 
| 2176 |  |  |  |  |  |  | $bad_slice_report_cref->( | 
| 2177 |  |  |  |  |  |  | "Incorrect value (expecting SCALAR-ref \\'$$reference_val')", | 
| 2178 |  |  |  |  |  |  | $row_idx, | 
| 2179 |  |  |  |  |  |  | $col_idx, | 
| 2180 |  |  |  |  |  |  | ); | 
| 2181 |  |  |  |  |  |  | } | 
| 2182 |  |  |  |  |  |  | elsif ($$val ne $$reference_val) { | 
| 2183 |  |  |  |  |  |  | $bad_slice_report_cref->( | 
| 2184 |  |  |  |  |  |  | "Inconsistent literal SQL value (expecting \\'$$reference_val')", | 
| 2185 |  |  |  |  |  |  | $row_idx, | 
| 2186 |  |  |  |  |  |  | $col_idx, | 
| 2187 |  |  |  |  |  |  | ); | 
| 2188 |  |  |  |  |  |  | } | 
| 2189 |  |  |  |  |  |  | } | 
| 2190 |  |  |  |  |  |  | elsif (! defined $serialized_bind_type_by_col_idx->{$col_idx} ) {  # regular non-literal value | 
| 2191 |  |  |  |  |  |  | if (is_literal_value($val)) { | 
| 2192 |  |  |  |  |  |  | $bad_slice_report_cref->("Literal SQL found where a plain bind value is expected", $row_idx, $col_idx); | 
| 2193 |  |  |  |  |  |  | } | 
| 2194 |  |  |  |  |  |  | } | 
| 2195 |  |  |  |  |  |  | else {  # binds from a \[], compare type and attrs | 
| 2196 |  |  |  |  |  |  | if (ref $val ne 'REF' or ref $$val ne 'ARRAY') { | 
| 2197 |  |  |  |  |  |  | $bad_slice_report_cref->( | 
| 2198 |  |  |  |  |  |  | "Incorrect value (expecting ARRAYREF-ref \\['${$reference_val}->[0]', ... ])", | 
| 2199 |  |  |  |  |  |  | $row_idx, | 
| 2200 |  |  |  |  |  |  | $col_idx, | 
| 2201 |  |  |  |  |  |  | ); | 
| 2202 |  |  |  |  |  |  | } | 
| 2203 |  |  |  |  |  |  | # start drilling down and bail out early on identical refs | 
| 2204 |  |  |  |  |  |  | elsif ( | 
| 2205 |  |  |  |  |  |  | $reference_val != $val | 
| 2206 |  |  |  |  |  |  | or | 
| 2207 |  |  |  |  |  |  | $$reference_val != $$val | 
| 2208 |  |  |  |  |  |  | ) { | 
| 2209 |  |  |  |  |  |  | if (${$val}->[0] ne ${$reference_val}->[0]) { | 
| 2210 |  |  |  |  |  |  | $bad_slice_report_cref->( | 
| 2211 |  |  |  |  |  |  | "Inconsistent literal/bind SQL (expecting \\['${$reference_val}->[0]', ... ])", | 
| 2212 |  |  |  |  |  |  | $row_idx, | 
| 2213 |  |  |  |  |  |  | $col_idx, | 
| 2214 |  |  |  |  |  |  | ); | 
| 2215 |  |  |  |  |  |  | } | 
| 2216 |  |  |  |  |  |  | # need to check the bind attrs - a bind will happen only once for | 
| 2217 |  |  |  |  |  |  | # the entire dataset, so any changes further down will be ignored. | 
| 2218 |  |  |  |  |  |  | elsif ( | 
| 2219 |  |  |  |  |  |  | $serialized_bind_type_by_col_idx->{$col_idx} | 
| 2220 |  |  |  |  |  |  | ne | 
| 2221 |  |  |  |  |  |  | serialize [ | 
| 2222 |  |  |  |  |  |  | map | 
| 2223 |  |  |  |  |  |  | { $_->[0] } | 
| 2224 |  |  |  |  |  |  | @{$self->_resolve_bindattrs( | 
| 2225 |  |  |  |  |  |  | $source, [ @{$$val}[1 .. $#$$val] ], $colinfos, | 
| 2226 |  |  |  |  |  |  | )} | 
| 2227 |  |  |  |  |  |  | ] | 
| 2228 |  |  |  |  |  |  | ) { | 
| 2229 |  |  |  |  |  |  | $bad_slice_report_cref->( | 
| 2230 |  |  |  |  |  |  | 'Differing bind attributes on literal/bind values not supported', | 
| 2231 |  |  |  |  |  |  | $row_idx, | 
| 2232 |  |  |  |  |  |  | $col_idx, | 
| 2233 |  |  |  |  |  |  | ); | 
| 2234 |  |  |  |  |  |  | } | 
| 2235 |  |  |  |  |  |  | } | 
| 2236 |  |  |  |  |  |  | } | 
| 2237 |  |  |  |  |  |  | } | 
| 2238 |  |  |  |  |  |  | } | 
| 2239 |  |  |  |  |  |  |  | 
| 2240 |  |  |  |  |  |  | # neither _dbh_execute_for_fetch, nor _dbh_execute_inserts_with_no_binds | 
| 2241 |  |  |  |  |  |  | # are atomic (even if execute_for_fetch is a single call). Thus a safety | 
| 2242 |  |  |  |  |  |  | # scope guard | 
| 2243 |  |  |  |  |  |  | my $guard = $self->txn_scope_guard; | 
| 2244 |  |  |  |  |  |  |  | 
| 2245 |  |  |  |  |  |  | $self->_query_start( $sql, @$proto_bind ? [[undef => '__BULK_INSERT__' ]] : () ); | 
| 2246 |  |  |  |  |  |  | my $sth = $self->_prepare_sth($self->_dbh, $sql); | 
| 2247 |  |  |  |  |  |  | my $rv = do { | 
| 2248 |  |  |  |  |  |  | if (@$proto_bind) { | 
| 2249 |  |  |  |  |  |  | # proto bind contains the information on which pieces of $data to pull | 
| 2250 |  |  |  |  |  |  | # $cols is passed in only for prettier error-reporting | 
| 2251 |  |  |  |  |  |  | $self->_dbh_execute_for_fetch( $source, $sth, $proto_bind, $cols, $data ); | 
| 2252 |  |  |  |  |  |  | } | 
| 2253 |  |  |  |  |  |  | else { | 
| 2254 |  |  |  |  |  |  | # bind_param_array doesn't work if there are no binds | 
| 2255 |  |  |  |  |  |  | $self->_dbh_execute_inserts_with_no_binds( $sth, scalar @$data ); | 
| 2256 |  |  |  |  |  |  | } | 
| 2257 |  |  |  |  |  |  | }; | 
| 2258 |  |  |  |  |  |  |  | 
| 2259 |  |  |  |  |  |  | $self->_query_end( $sql, @$proto_bind ? [[ undef => '__BULK_INSERT__' ]] : () ); | 
| 2260 |  |  |  |  |  |  |  | 
| 2261 |  |  |  |  |  |  | $guard->commit; | 
| 2262 |  |  |  |  |  |  |  | 
| 2263 |  |  |  |  |  |  | return wantarray ? ($rv, $sth, @$proto_bind) : $rv; | 
| 2264 |  |  |  |  |  |  | } | 
| 2265 |  |  |  |  |  |  |  | 
| 2266 |  |  |  |  |  |  | # execute_for_fetch is capable of returning data just fine (it means it | 
| 2267 |  |  |  |  |  |  | # can be used for INSERT...RETURNING and UPDATE...RETURNING. Since this | 
| 2268 |  |  |  |  |  |  | # is the void-populate fast-path we will just ignore this altogether | 
| 2269 |  |  |  |  |  |  | # for the time being. | 
| 2270 |  |  |  |  |  |  | sub _dbh_execute_for_fetch { | 
| 2271 | 7644 |  |  | 7644 |  | 10955 | my ($self, $source, $sth, $proto_bind, $cols, $data) = @_; | 
| 2272 |  |  |  |  |  |  |  | 
| 2273 |  |  |  |  |  |  | # If we have any bind attributes to take care of, we will bind the | 
| 2274 |  |  |  |  |  |  | # proto-bind data (which will never be used by execute_for_fetch) | 
| 2275 |  |  |  |  |  |  | # However since column bindtypes are "sticky", this is sufficient | 
| 2276 |  |  |  |  |  |  | # to get the DBD to apply the bindtype to all values later on | 
| 2277 | 7644 |  |  |  |  | 20692 | my $bind_attrs = $self->_dbi_attrs_for_bind($source, $proto_bind); | 
| 2278 |  |  |  |  |  |  |  | 
| 2279 | 7644 |  |  |  |  | 12125 | for my $i (0 .. $#$proto_bind) { | 
| 2280 | 21911 | 100 |  |  |  | 79579 | $sth->bind_param ( | 
| 2281 |  |  |  |  |  |  | $i+1, # DBI bind indexes are 1-based | 
| 2282 |  |  |  |  |  |  | $proto_bind->[$i][1], | 
| 2283 |  |  |  |  |  |  | $bind_attrs->[$i], | 
| 2284 |  |  |  |  |  |  | ) if defined $bind_attrs->[$i]; | 
| 2285 |  |  |  |  |  |  | } | 
| 2286 |  |  |  |  |  |  |  | 
| 2287 |  |  |  |  |  |  | # At this point $data slots named in the _bind_data_slice_idx of | 
| 2288 |  |  |  |  |  |  | # each piece of $proto_bind are either \[]s or plain values to be | 
| 2289 |  |  |  |  |  |  | # passed in. Construct the dispensing coderef. *NOTE* the order | 
| 2290 |  |  |  |  |  |  | # of $data will differ from this of the ?s in the SQL (due to | 
| 2291 |  |  |  |  |  |  | # alphabetical ordering by colname). We actually do want to | 
| 2292 |  |  |  |  |  |  | # preserve this behavior so that prepare_cached has a better | 
| 2293 |  |  |  |  |  |  | # chance of matching on unrelated calls | 
| 2294 |  |  |  |  |  |  |  | 
| 2295 | 7644 |  |  |  |  | 7986 | my $fetch_row_idx = -1; # saner loop this way | 
| 2296 |  |  |  |  |  |  | my $fetch_tuple = sub { | 
| 2297 | 44509 | 100 |  | 44509 |  | 1070111 | return undef if ++$fetch_row_idx > $#$data; | 
| 2298 |  |  |  |  |  |  |  | 
| 2299 |  |  |  |  |  |  | return [ map { | 
| 2300 |  |  |  |  |  |  | my $v = ! defined $_->{_literal_bind_subindex} | 
| 2301 |  |  |  |  |  |  |  | 
| 2302 |  |  |  |  |  |  | ? $data->[ $fetch_row_idx ]->[ $_->{_bind_data_slice_idx} ] | 
| 2303 |  |  |  |  |  |  |  | 
| 2304 |  |  |  |  |  |  | # There are no attributes to resolve here - we already did everything | 
| 2305 |  |  |  |  |  |  | # when we constructed proto_bind. However we still want to sanity-check | 
| 2306 |  |  |  |  |  |  | # what the user supplied, so pass stuff through to the resolver *anyway* | 
| 2307 |  |  |  |  |  |  | : $self->_resolve_bindattrs ( | 
| 2308 |  |  |  |  |  |  | undef,  # a fake rsrc | 
| 2309 | 103152 | 100 |  |  |  | 150076 | [ ${ $data->[ $fetch_row_idx ]->[ $_->{_bind_data_slice_idx} ]}->[ $_->{_literal_bind_subindex} ] ], | 
|  | 54 |  |  |  |  | 156 |  | 
| 2310 |  |  |  |  |  |  | {},     # a fake column_info bag | 
| 2311 |  |  |  |  |  |  | )->[0][1] | 
| 2312 |  |  |  |  |  |  | ; | 
| 2313 |  |  |  |  |  |  |  | 
| 2314 |  |  |  |  |  |  | # FIXME SUBOPTIMAL - DBI needs fixing to always stringify regardless of DBD | 
| 2315 |  |  |  |  |  |  | # For the time being forcibly stringify whatever is stringifiable | 
| 2316 | 103152 | 100 | 66 |  |  | 248153 | (length ref $v and is_plain_value $v) | 
| 2317 |  |  |  |  |  |  | ? "$v" | 
| 2318 |  |  |  |  |  |  | : $v | 
| 2319 |  |  |  |  |  |  | ; | 
| 2320 | 36865 |  |  |  |  | 42587 | } map { $_->[0] } @$proto_bind ]; | 
|  | 103152 |  |  |  |  | 99095 |  | 
| 2321 | 7644 |  |  |  |  | 32907 | }; | 
| 2322 |  |  |  |  |  |  |  | 
| 2323 | 7644 |  |  |  |  | 9325 | my $tuple_status = []; | 
| 2324 | 7644 |  |  |  |  | 7971 | my ($rv, $err); | 
| 2325 |  |  |  |  |  |  | try { | 
| 2326 | 7644 |  |  | 7644 |  | 349203 | $rv = $sth->execute_for_fetch( | 
| 2327 |  |  |  |  |  |  | $fetch_tuple, | 
| 2328 |  |  |  |  |  |  | $tuple_status, | 
| 2329 |  |  |  |  |  |  | ); | 
| 2330 |  |  |  |  |  |  | } | 
| 2331 |  |  |  |  |  |  | catch { | 
| 2332 | 2 |  |  | 2 |  | 27 | $err = shift; | 
| 2333 | 7644 |  |  |  |  | 35208 | }; | 
| 2334 |  |  |  |  |  |  |  | 
| 2335 |  |  |  |  |  |  | # Not all DBDs are create equal. Some throw on error, some return | 
| 2336 |  |  |  |  |  |  | # an undef $rv, and some set $sth->err - try whatever we can | 
| 2337 | 7644 | 50 | 0 |  |  | 179872 | $err = ($sth->errstr || 'UNKNOWN ERROR ($sth->errstr is unset)') if ( | 
|  |  |  | 33 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 2338 |  |  |  |  |  |  | ! defined $err | 
| 2339 |  |  |  |  |  |  | and | 
| 2340 |  |  |  |  |  |  | ( !defined $rv or $sth->err ) | 
| 2341 |  |  |  |  |  |  | ); | 
| 2342 |  |  |  |  |  |  |  | 
| 2343 |  |  |  |  |  |  | # Statement must finish even if there was an exception. | 
| 2344 |  |  |  |  |  |  | try { | 
| 2345 | 7644 |  |  | 7644 |  | 331836 | $sth->finish | 
| 2346 |  |  |  |  |  |  | } | 
| 2347 |  |  |  |  |  |  | catch { | 
| 2348 | 0 | 0 |  | 0 |  | 0 | $err = shift unless defined $err | 
| 2349 | 7644 |  |  |  |  | 83992 | }; | 
| 2350 |  |  |  |  |  |  |  | 
| 2351 | 7644 | 100 |  |  |  | 72624 | if (defined $err) { | 
| 2352 | 2 |  |  |  |  | 4 | my $i = 0; | 
| 2353 | 2 |  | 66 |  |  | 20 | ++$i while $i <= $#$tuple_status && !ref $tuple_status->[$i]; | 
| 2354 |  |  |  |  |  |  |  | 
| 2355 | 2 | 50 |  |  |  | 6 | $self->throw_exception("Unexpected populate error: $err") | 
| 2356 |  |  |  |  |  |  | if ($i > $#$tuple_status); | 
| 2357 |  |  |  |  |  |  |  | 
| 2358 | 2 |  |  |  |  | 12 | require Data::Dumper::Concise; | 
| 2359 |  |  |  |  |  |  | $self->throw_exception(sprintf "execute_for_fetch() aborted with '%s' at populate slice:\n%s", | 
| 2360 |  |  |  |  |  |  | ($tuple_status->[$i][1] || $err), | 
| 2361 | 2 |  | 33 |  |  | 9 | Data::Dumper::Concise::Dumper( { map { $cols->[$_] => $data->[$i][$_] } (0 .. $#$cols) } ), | 
|  | 5 |  |  |  |  | 18 |  | 
| 2362 |  |  |  |  |  |  | ); | 
| 2363 |  |  |  |  |  |  | } | 
| 2364 |  |  |  |  |  |  |  | 
| 2365 | 7642 |  |  |  |  | 45683 | return $rv; | 
| 2366 |  |  |  |  |  |  | } | 
| 2367 |  |  |  |  |  |  |  | 
| 2368 |  |  |  |  |  |  | sub _dbh_execute_inserts_with_no_binds { | 
| 2369 | 2 |  |  | 2 |  | 4 | my ($self, $sth, $count) = @_; | 
| 2370 |  |  |  |  |  |  |  | 
| 2371 | 2 |  |  |  |  | 2 | my $err; | 
| 2372 |  |  |  |  |  |  | try { | 
| 2373 | 2 |  |  | 2 |  | 69 | my $dbh = $self->_get_dbh; | 
| 2374 | 2 |  |  |  |  | 32 | local $dbh->{RaiseError} = 1; | 
| 2375 | 2 |  |  |  |  | 31 | local $dbh->{PrintError} = 0; | 
| 2376 |  |  |  |  |  |  |  | 
| 2377 | 2 |  |  |  |  | 94 | $sth->execute foreach 1..$count; | 
| 2378 |  |  |  |  |  |  | } | 
| 2379 |  |  |  |  |  |  | catch { | 
| 2380 | 0 |  |  | 0 |  | 0 | $err = shift; | 
| 2381 | 2 |  |  |  |  | 37 | }; | 
| 2382 |  |  |  |  |  |  |  | 
| 2383 |  |  |  |  |  |  | # Make sure statement is finished even if there was an exception. | 
| 2384 |  |  |  |  |  |  | try { | 
| 2385 | 2 |  |  | 2 |  | 68 | $sth->finish | 
| 2386 |  |  |  |  |  |  | } | 
| 2387 |  |  |  |  |  |  | catch { | 
| 2388 | 0 | 0 |  | 0 |  | 0 | $err = shift unless defined $err; | 
| 2389 | 2 |  |  |  |  | 37 | }; | 
| 2390 |  |  |  |  |  |  |  | 
| 2391 | 2 | 50 |  |  |  | 24 | $self->throw_exception($err) if defined $err; | 
| 2392 |  |  |  |  |  |  |  | 
| 2393 | 2 |  |  |  |  | 4 | return $count; | 
| 2394 |  |  |  |  |  |  | } | 
| 2395 |  |  |  |  |  |  |  | 
| 2396 |  |  |  |  |  |  | sub update { | 
| 2397 |  |  |  |  |  |  | #my ($self, $source, @args) = @_; | 
| 2398 |  |  |  |  |  |  | shift->_execute('update', @_); | 
| 2399 |  |  |  |  |  |  | } | 
| 2400 |  |  |  |  |  |  |  | 
| 2401 |  |  |  |  |  |  |  | 
| 2402 |  |  |  |  |  |  | sub delete { | 
| 2403 |  |  |  |  |  |  | #my ($self, $source, @args) = @_; | 
| 2404 |  |  |  |  |  |  | shift->_execute('delete', @_); | 
| 2405 |  |  |  |  |  |  | } | 
| 2406 |  |  |  |  |  |  |  | 
| 2407 |  |  |  |  |  |  | sub _select { | 
| 2408 | 7095 |  |  | 7095 |  | 9441 | my $self = shift; | 
| 2409 | 7095 |  |  |  |  | 17284 | $self->_execute($self->_select_args(@_)); | 
| 2410 |  |  |  |  |  |  | } | 
| 2411 |  |  |  |  |  |  |  | 
| 2412 |  |  |  |  |  |  | sub _select_args_to_query { | 
| 2413 | 749 |  |  | 749 |  | 9401 | my $self = shift; | 
| 2414 |  |  |  |  |  |  |  | 
| 2415 |  |  |  |  |  |  | $self->throw_exception( | 
| 2416 |  |  |  |  |  |  | "Unable to generate limited query representation with 'software_limit' enabled" | 
| 2417 | 749 | 50 | 33 |  |  | 2199 | ) if ($_[3]->{software_limit} and ($_[3]->{offset} or $_[3]->{rows}) ); | 
|  |  |  | 66 |  |  |  |  | 
| 2418 |  |  |  |  |  |  |  | 
| 2419 |  |  |  |  |  |  | # my ($op, $ident, $select, $cond, $rs_attrs, $rows, $offset) | 
| 2420 |  |  |  |  |  |  | #  = $self->_select_args($ident, $select, $cond, $attrs); | 
| 2421 | 748 |  |  |  |  | 2365 | my ($op, $ident, @args) = | 
| 2422 |  |  |  |  |  |  | $self->_select_args(@_); | 
| 2423 |  |  |  |  |  |  |  | 
| 2424 |  |  |  |  |  |  | # my ($sql, $prepared_bind) = $self->_gen_sql_bind($op, $ident, [ $select, $cond, $rs_attrs, $rows, $offset ]); | 
| 2425 | 748 |  |  |  |  | 3092 | my ($sql, $bind) = $self->_gen_sql_bind($op, $ident, \@args); | 
| 2426 |  |  |  |  |  |  |  | 
| 2427 |  |  |  |  |  |  | # reuse the bind arrayref | 
| 2428 | 745 |  |  |  |  | 1107 | unshift @{$bind}, "($sql)"; | 
|  | 745 |  |  |  |  | 2746 |  | 
| 2429 | 745 |  |  |  |  | 5354 | \$bind; | 
| 2430 |  |  |  |  |  |  | } | 
| 2431 |  |  |  |  |  |  |  | 
| 2432 |  |  |  |  |  |  | sub _select_args { | 
| 2433 | 7843 |  |  | 7843 |  | 13352 | my ($self, $ident, $select, $where, $orig_attrs) = @_; | 
| 2434 |  |  |  |  |  |  |  | 
| 2435 |  |  |  |  |  |  | # FIXME - that kind of caching would be nice to have | 
| 2436 |  |  |  |  |  |  | # however currently we *may* pass the same $orig_attrs | 
| 2437 |  |  |  |  |  |  | # with different ident/select/where | 
| 2438 |  |  |  |  |  |  | # the whole interface needs to be rethought, since it | 
| 2439 |  |  |  |  |  |  | # was centered around the flawed SQLA API. We can do | 
| 2440 |  |  |  |  |  |  | # soooooo much better now. But that is also another | 
| 2441 |  |  |  |  |  |  | # battle... | 
| 2442 |  |  |  |  |  |  | #return ( | 
| 2443 |  |  |  |  |  |  | #  'select', $orig_attrs->{!args_as_stored_at_the_end_of_this_method!} | 
| 2444 |  |  |  |  |  |  | #) if $orig_attrs->{!args_as_stored_at_the_end_of_this_method!}; | 
| 2445 |  |  |  |  |  |  |  | 
| 2446 | 7843 |  |  |  |  | 155428 | my $sql_maker = $self->sql_maker; | 
| 2447 |  |  |  |  |  |  |  | 
| 2448 | 7843 |  |  |  |  | 70989 | my $attrs = { | 
| 2449 |  |  |  |  |  |  | %$orig_attrs, | 
| 2450 |  |  |  |  |  |  | select => $select, | 
| 2451 |  |  |  |  |  |  | from => $ident, | 
| 2452 |  |  |  |  |  |  | where => $where, | 
| 2453 |  |  |  |  |  |  | }; | 
| 2454 |  |  |  |  |  |  |  | 
| 2455 |  |  |  |  |  |  | # Sanity check the attributes (SQLMaker does it too, but | 
| 2456 |  |  |  |  |  |  | # in case of a software_limit we'll never reach there) | 
| 2457 | 7843 | 100 |  |  |  | 23590 | if (defined $attrs->{offset}) { | 
| 2458 |  |  |  |  |  |  | $self->throw_exception('A supplied offset attribute must be a non-negative integer') | 
| 2459 | 207 | 50 | 33 |  |  | 1828 | if ( $attrs->{offset} =~ /\D/ or $attrs->{offset} < 0 ); | 
| 2460 |  |  |  |  |  |  | } | 
| 2461 |  |  |  |  |  |  |  | 
| 2462 | 7843 | 100 |  |  |  | 22515 | if (defined $attrs->{rows}) { | 
|  |  | 100 |  |  |  |  |  | 
| 2463 |  |  |  |  |  |  | $self->throw_exception("The rows attribute must be a positive integer if present") | 
| 2464 | 1741 | 50 | 33 |  |  | 12233 | if ( $attrs->{rows} =~ /\D/ or $attrs->{rows} <= 0 ); | 
| 2465 |  |  |  |  |  |  | } | 
| 2466 |  |  |  |  |  |  | elsif ($attrs->{offset}) { | 
| 2467 |  |  |  |  |  |  | # MySQL actually recommends this approach.  I cringe. | 
| 2468 | 12 |  |  |  |  | 106 | $attrs->{rows} = $sql_maker->__max_int; | 
| 2469 |  |  |  |  |  |  | } | 
| 2470 |  |  |  |  |  |  |  | 
| 2471 |  |  |  |  |  |  | # see if we will need to tear the prefetch apart to satisfy group_by == select | 
| 2472 |  |  |  |  |  |  | # this is *extremely tricky* to get right, I am still not sure I did | 
| 2473 |  |  |  |  |  |  | # | 
| 2474 | 7843 |  |  |  |  | 8565 | my ($prefetch_needs_subquery, @limit_args); | 
| 2475 |  |  |  |  |  |  |  | 
| 2476 | 7843 | 100 | 66 |  |  | 73836 | if ( $attrs->{_grouped_by_distinct} and $attrs->{collapse} ) { | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  | 100 | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 2477 |  |  |  |  |  |  | # we already know there is a valid group_by (we made it) and we know it is | 
| 2478 |  |  |  |  |  |  | # intended to be based *only* on non-multi stuff | 
| 2479 |  |  |  |  |  |  | # short circuit the group_by parsing below | 
| 2480 | 11 |  |  |  |  | 26 | $prefetch_needs_subquery = 1; | 
| 2481 |  |  |  |  |  |  | } | 
| 2482 |  |  |  |  |  |  | elsif ( | 
| 2483 |  |  |  |  |  |  | # The rationale is that even if we do *not* have collapse, we still | 
| 2484 |  |  |  |  |  |  | # need to wrap the core grouped select/group_by in a subquery | 
| 2485 |  |  |  |  |  |  | # so that databases that care about group_by/select equivalence | 
| 2486 |  |  |  |  |  |  | # are happy (this includes MySQL in strict_mode) | 
| 2487 |  |  |  |  |  |  | # If any of the other joined tables are referenced in the group_by | 
| 2488 |  |  |  |  |  |  | # however - the user is on their own | 
| 2489 |  |  |  |  |  |  | ( $prefetch_needs_subquery or ! $attrs->{_simple_passthrough_construction} ) | 
| 2490 |  |  |  |  |  |  | and | 
| 2491 |  |  |  |  |  |  | $attrs->{group_by} | 
| 2492 |  |  |  |  |  |  | and | 
| 2493 | 47 |  |  |  |  | 544 | @{$attrs->{group_by}} | 
| 2494 |  |  |  |  |  |  | and | 
| 2495 |  |  |  |  |  |  | my $grp_aliases = try { # try{} because $attrs->{from} may be unreadable | 
| 2496 |  |  |  |  |  |  | $self->_resolve_aliastypes_from_select_args({ from => $attrs->{from}, group_by => $attrs->{group_by} }) | 
| 2497 | 47 |  |  | 47 |  | 2567 | } | 
| 2498 |  |  |  |  |  |  | ) { | 
| 2499 |  |  |  |  |  |  | # no aliases other than our own in group_by | 
| 2500 |  |  |  |  |  |  | # if there are - do not allow subquery even if limit is present | 
| 2501 | 47 | 50 |  |  |  | 678 | $prefetch_needs_subquery = ! scalar grep { $_ ne $attrs->{alias} } keys %{ $grp_aliases->{grouping} || {} }; | 
|  | 79 |  |  |  |  | 226 |  | 
|  | 47 |  |  |  |  | 188 |  | 
| 2502 |  |  |  |  |  |  | } | 
| 2503 |  |  |  |  |  |  | elsif ( $attrs->{rows} && $attrs->{collapse} ) { | 
| 2504 |  |  |  |  |  |  | # active collapse with a limit - that one is a no-brainer unless | 
| 2505 |  |  |  |  |  |  | # overruled by a group_by above | 
| 2506 | 61 |  |  |  |  | 96 | $prefetch_needs_subquery = 1; | 
| 2507 |  |  |  |  |  |  | } | 
| 2508 |  |  |  |  |  |  |  | 
| 2509 | 7843 | 100 |  |  |  | 22220 | if ($prefetch_needs_subquery) { | 
|  |  | 100 |  |  |  |  |  | 
| 2510 | 87 |  |  |  |  | 663 | $attrs = $self->_adjust_select_args_for_complex_prefetch ($attrs); | 
| 2511 |  |  |  |  |  |  | } | 
| 2512 |  |  |  |  |  |  | elsif (! $attrs->{software_limit} ) { | 
| 2513 |  |  |  |  |  |  | push @limit_args, ( | 
| 2514 |  |  |  |  |  |  | $attrs->{rows} || (), | 
| 2515 | 7750 |  | 66 |  |  | 40532 | $attrs->{offset} || (), | 
|  |  |  | 100 |  |  |  |  | 
| 2516 |  |  |  |  |  |  | ); | 
| 2517 |  |  |  |  |  |  | } | 
| 2518 |  |  |  |  |  |  |  | 
| 2519 |  |  |  |  |  |  | # try to simplify the joinmap further (prune unreferenced type-single joins) | 
| 2520 | 7842 | 100 | 66 |  |  | 65051 | if ( | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 2521 |  |  |  |  |  |  | ! $prefetch_needs_subquery  # already pruned | 
| 2522 |  |  |  |  |  |  | and | 
| 2523 |  |  |  |  |  |  | ref $attrs->{from} | 
| 2524 |  |  |  |  |  |  | and | 
| 2525 |  |  |  |  |  |  | reftype $attrs->{from} eq 'ARRAY' | 
| 2526 |  |  |  |  |  |  | and | 
| 2527 | 7753 |  |  |  |  | 23859 | @{$attrs->{from}} != 1 | 
| 2528 |  |  |  |  |  |  | ) { | 
| 2529 | 844 |  |  |  |  | 4666 | ($attrs->{from}, $attrs->{_aliastypes}) = $self->_prune_unused_joins ($attrs); | 
| 2530 |  |  |  |  |  |  | } | 
| 2531 |  |  |  |  |  |  |  | 
| 2532 |  |  |  |  |  |  | # FIXME this is a gross, inefficient, largely incorrect and fragile hack | 
| 2533 |  |  |  |  |  |  | # during the result inflation stage we *need* to know what was the aliastype | 
| 2534 |  |  |  |  |  |  | # map as sqla saw it when the final pieces of SQL were being assembled | 
| 2535 |  |  |  |  |  |  | # Originally we simply carried around the entirety of $attrs, but this | 
| 2536 |  |  |  |  |  |  | # resulted in resultsets that are being reused growing continuously, as | 
| 2537 |  |  |  |  |  |  | # the hash in question grew deeper and deeper. | 
| 2538 |  |  |  |  |  |  | # Instead hand-pick what to take with us here (we actually don't need much | 
| 2539 |  |  |  |  |  |  | # at this point just the map itself) | 
| 2540 | 7842 |  |  |  |  | 15053 | $orig_attrs->{_last_sqlmaker_alias_map} = $attrs->{_aliastypes}; | 
| 2541 |  |  |  |  |  |  |  | 
| 2542 |  |  |  |  |  |  | ### | 
| 2543 |  |  |  |  |  |  | #   my $alias2source = $self->_resolve_ident_sources ($ident); | 
| 2544 |  |  |  |  |  |  | # | 
| 2545 |  |  |  |  |  |  | # This would be the point to deflate anything found in $attrs->{where} | 
| 2546 |  |  |  |  |  |  | # (and leave $attrs->{bind} intact). Problem is - inflators historically | 
| 2547 |  |  |  |  |  |  | # expect a result object. And all we have is a resultsource (it is trivial | 
| 2548 |  |  |  |  |  |  | # to extract deflator coderefs via $alias2source above). | 
| 2549 |  |  |  |  |  |  | # | 
| 2550 |  |  |  |  |  |  | # I don't see a way forward other than changing the way deflators are | 
| 2551 |  |  |  |  |  |  | # invoked, and that's just bad... | 
| 2552 |  |  |  |  |  |  | ### | 
| 2553 |  |  |  |  |  |  |  | 
| 2554 | 7842 |  |  |  |  | 9914 | return ( 'select', @{$attrs}{qw(from select where)}, $attrs, @limit_args ); | 
|  | 7842 |  |  |  |  | 36978 |  | 
| 2555 |  |  |  |  |  |  | } | 
| 2556 |  |  |  |  |  |  |  | 
| 2557 |  |  |  |  |  |  | # Returns a counting SELECT for a simple count | 
| 2558 |  |  |  |  |  |  | # query. Abstracted so that a storage could override | 
| 2559 |  |  |  |  |  |  | # this to { count => 'firstcol' } or whatever makes | 
| 2560 |  |  |  |  |  |  | # sense as a performance optimization | 
| 2561 |  |  |  |  |  |  | sub _count_select { | 
| 2562 |  |  |  |  |  |  | #my ($self, $source, $rs_attrs) = @_; | 
| 2563 | 606 |  |  | 606 |  | 13298 | return { count => '*' }; | 
| 2564 |  |  |  |  |  |  | } | 
| 2565 |  |  |  |  |  |  |  | 
| 2566 |  |  |  |  |  |  | =head2 select | 
| 2567 |  |  |  |  |  |  |  | 
| 2568 |  |  |  |  |  |  | =over 4 | 
| 2569 |  |  |  |  |  |  |  | 
| 2570 |  |  |  |  |  |  | =item Arguments: $ident, $select, $condition, $attrs | 
| 2571 |  |  |  |  |  |  |  | 
| 2572 |  |  |  |  |  |  | =back | 
| 2573 |  |  |  |  |  |  |  | 
| 2574 |  |  |  |  |  |  | Handle a SQL select statement. | 
| 2575 |  |  |  |  |  |  |  | 
| 2576 |  |  |  |  |  |  | =cut | 
| 2577 |  |  |  |  |  |  |  | 
| 2578 |  |  |  |  |  |  | sub select { | 
| 2579 |  |  |  |  |  |  | my $self = shift; | 
| 2580 |  |  |  |  |  |  | my ($ident, $select, $condition, $attrs) = @_; | 
| 2581 |  |  |  |  |  |  | return $self->cursor_class->new($self, \@_, $attrs); | 
| 2582 |  |  |  |  |  |  | } | 
| 2583 |  |  |  |  |  |  |  | 
| 2584 |  |  |  |  |  |  | sub select_single { | 
| 2585 |  |  |  |  |  |  | my $self = shift; | 
| 2586 |  |  |  |  |  |  | my ($rv, $sth, @bind) = $self->_select(@_); | 
| 2587 |  |  |  |  |  |  | my @row = $sth->fetchrow_array; | 
| 2588 |  |  |  |  |  |  | my @nextrow = $sth->fetchrow_array if @row; | 
| 2589 |  |  |  |  |  |  | if(@row && @nextrow) { | 
| 2590 |  |  |  |  |  |  | carp "Query returned more than one row.  SQL that returns multiple rows is DEPRECATED for ->find and ->single"; | 
| 2591 |  |  |  |  |  |  | } | 
| 2592 |  |  |  |  |  |  | # Need to call finish() to work round broken DBDs | 
| 2593 |  |  |  |  |  |  | $sth->finish(); | 
| 2594 |  |  |  |  |  |  | return @row; | 
| 2595 |  |  |  |  |  |  | } | 
| 2596 |  |  |  |  |  |  |  | 
| 2597 |  |  |  |  |  |  | =head2 sql_limit_dialect | 
| 2598 |  |  |  |  |  |  |  | 
| 2599 |  |  |  |  |  |  | This is an accessor for the default SQL limit dialect used by a particular | 
| 2600 |  |  |  |  |  |  | storage driver. Can be overridden by supplying an explicit L | 
| 2601 |  |  |  |  |  |  | to L. For a list of available limit dialects | 
| 2602 |  |  |  |  |  |  | see L. | 
| 2603 |  |  |  |  |  |  |  | 
| 2604 |  |  |  |  |  |  | =cut | 
| 2605 |  |  |  |  |  |  |  | 
| 2606 |  |  |  |  |  |  | sub _dbh_columns_info_for { | 
| 2607 | 4 |  |  | 4 |  | 8 | my ($self, $dbh, $table) = @_; | 
| 2608 |  |  |  |  |  |  |  | 
| 2609 | 4 | 50 |  |  |  | 45 | if ($dbh->can('column_info')) { | 
| 2610 | 4 |  |  |  |  | 7 | my %result; | 
| 2611 |  |  |  |  |  |  | my $caught; | 
| 2612 |  |  |  |  |  |  | try { | 
| 2613 | 4 | 50 |  | 4 |  | 202 | my ($schema,$tab) = $table =~ /^(.+?)\.(.+)$/ ? ($1,$2) : (undef,$table); | 
| 2614 | 4 |  |  |  |  | 28 | my $sth = $dbh->column_info( undef,$schema, $tab, '%' ); | 
| 2615 | 4 |  |  |  |  | 9296 | $sth->execute(); | 
| 2616 | 4 |  |  |  |  | 103 | while ( my $info = $sth->fetchrow_hashref() ){ | 
| 2617 | 14 |  |  |  |  | 275 | my %column_info; | 
| 2618 | 14 |  |  |  |  | 30 | $column_info{data_type}   = $info->{TYPE_NAME}; | 
| 2619 | 14 |  |  |  |  | 20 | $column_info{size}      = $info->{COLUMN_SIZE}; | 
| 2620 | 14 | 100 |  |  |  | 31 | $column_info{is_nullable}   = $info->{NULLABLE} ? 1 : 0; | 
| 2621 | 14 |  |  |  |  | 16 | $column_info{default_value} = $info->{COLUMN_DEF}; | 
| 2622 | 14 |  |  |  |  | 16 | my $col_name = $info->{COLUMN_NAME}; | 
| 2623 | 14 |  |  |  |  | 23 | $col_name =~ s/^\"(.*)\"$/$1/; | 
| 2624 |  |  |  |  |  |  |  | 
| 2625 | 14 |  |  |  |  | 152 | $result{$col_name} = \%column_info; | 
| 2626 |  |  |  |  |  |  | } | 
| 2627 |  |  |  |  |  |  | } catch { | 
| 2628 | 0 |  |  | 0 |  | 0 | $caught = 1; | 
| 2629 | 4 |  |  |  |  | 38 | }; | 
| 2630 | 4 | 50 | 50 |  |  | 315 | return \%result if !$caught && scalar keys %result; | 
| 2631 |  |  |  |  |  |  | } | 
| 2632 |  |  |  |  |  |  |  | 
| 2633 | 0 |  |  |  |  | 0 | my %result; | 
| 2634 | 0 |  |  |  |  | 0 | my $sth = $dbh->prepare($self->sql_maker->select($table, undef, \'1 = 0')); | 
| 2635 | 0 |  |  |  |  | 0 | $sth->execute; | 
| 2636 | 0 |  |  |  |  | 0 | my @columns = @{$sth->{NAME_lc}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 2637 | 0 |  |  |  |  | 0 | for my $i ( 0 .. $#columns ){ | 
| 2638 | 0 |  |  |  |  | 0 | my %column_info; | 
| 2639 | 0 |  |  |  |  | 0 | $column_info{data_type} = $sth->{TYPE}->[$i]; | 
| 2640 | 0 |  |  |  |  | 0 | $column_info{size} = $sth->{PRECISION}->[$i]; | 
| 2641 | 0 | 0 |  |  |  | 0 | $column_info{is_nullable} = $sth->{NULLABLE}->[$i] ? 1 : 0; | 
| 2642 |  |  |  |  |  |  |  | 
| 2643 | 0 | 0 |  |  |  | 0 | if ($column_info{data_type} =~ m/^(.*?)\((.*?)\)$/) { | 
| 2644 | 0 |  |  |  |  | 0 | $column_info{data_type} = $1; | 
| 2645 | 0 |  |  |  |  | 0 | $column_info{size}    = $2; | 
| 2646 |  |  |  |  |  |  | } | 
| 2647 |  |  |  |  |  |  |  | 
| 2648 | 0 |  |  |  |  | 0 | $result{$columns[$i]} = \%column_info; | 
| 2649 |  |  |  |  |  |  | } | 
| 2650 | 0 |  |  |  |  | 0 | $sth->finish; | 
| 2651 |  |  |  |  |  |  |  | 
| 2652 | 0 |  |  |  |  | 0 | foreach my $col (keys %result) { | 
| 2653 | 0 |  |  |  |  | 0 | my $colinfo = $result{$col}; | 
| 2654 | 0 |  |  |  |  | 0 | my $type_num = $colinfo->{data_type}; | 
| 2655 | 0 |  |  |  |  | 0 | my $type_name; | 
| 2656 | 0 | 0 | 0 |  |  | 0 | if(defined $type_num && $dbh->can('type_info')) { | 
| 2657 | 0 |  |  |  |  | 0 | my $type_info = $dbh->type_info($type_num); | 
| 2658 | 0 | 0 |  |  |  | 0 | $type_name = $type_info->{TYPE_NAME} if $type_info; | 
| 2659 | 0 | 0 |  |  |  | 0 | $colinfo->{data_type} = $type_name if $type_name; | 
| 2660 |  |  |  |  |  |  | } | 
| 2661 |  |  |  |  |  |  | } | 
| 2662 |  |  |  |  |  |  |  | 
| 2663 | 0 |  |  |  |  | 0 | return \%result; | 
| 2664 |  |  |  |  |  |  | } | 
| 2665 |  |  |  |  |  |  |  | 
| 2666 |  |  |  |  |  |  | sub columns_info_for { | 
| 2667 | 4 |  |  | 4 | 1 | 1678 | my ($self, $table) = @_; | 
| 2668 | 4 |  |  |  |  | 16 | $self->_dbh_columns_info_for ($self->_get_dbh, $table); | 
| 2669 |  |  |  |  |  |  | } | 
| 2670 |  |  |  |  |  |  |  | 
| 2671 |  |  |  |  |  |  | =head2 last_insert_id | 
| 2672 |  |  |  |  |  |  |  | 
| 2673 |  |  |  |  |  |  | Return the row id of the last insert. | 
| 2674 |  |  |  |  |  |  |  | 
| 2675 |  |  |  |  |  |  | =cut | 
| 2676 |  |  |  |  |  |  |  | 
| 2677 |  |  |  |  |  |  | sub _dbh_last_insert_id { | 
| 2678 | 1227 |  |  | 1227 |  | 1844 | my ($self, $dbh, $source, $col) = @_; | 
| 2679 |  |  |  |  |  |  |  | 
| 2680 | 1227 |  |  | 1227 |  | 8324 | my $id = try { $dbh->last_insert_id (undef, undef, $source->name, $col) }; | 
|  | 1227 |  |  |  |  | 51627 |  | 
| 2681 |  |  |  |  |  |  |  | 
| 2682 | 1227 | 50 |  |  |  | 15587 | return $id if defined $id; | 
| 2683 |  |  |  |  |  |  |  | 
| 2684 | 0 |  |  |  |  | 0 | my $class = ref $self; | 
| 2685 | 0 |  |  |  |  | 0 | $self->throw_exception ("No storage specific _dbh_last_insert_id() method implemented in $class, and the generic DBI::last_insert_id() failed"); | 
| 2686 |  |  |  |  |  |  | } | 
| 2687 |  |  |  |  |  |  |  | 
| 2688 |  |  |  |  |  |  | sub last_insert_id { | 
| 2689 | 1227 |  |  | 1227 | 1 | 1896 | my $self = shift; | 
| 2690 | 1227 |  |  |  |  | 4629 | $self->_dbh_last_insert_id ($self->_dbh, @_); | 
| 2691 |  |  |  |  |  |  | } | 
| 2692 |  |  |  |  |  |  |  | 
| 2693 |  |  |  |  |  |  | =head2 _native_data_type | 
| 2694 |  |  |  |  |  |  |  | 
| 2695 |  |  |  |  |  |  | =over 4 | 
| 2696 |  |  |  |  |  |  |  | 
| 2697 |  |  |  |  |  |  | =item Arguments: $type_name | 
| 2698 |  |  |  |  |  |  |  | 
| 2699 |  |  |  |  |  |  | =back | 
| 2700 |  |  |  |  |  |  |  | 
| 2701 |  |  |  |  |  |  | This API is B, will almost definitely change in the future, and | 
| 2702 |  |  |  |  |  |  | currently only used by L<::AutoCast|DBIx::Class::Storage::DBI::AutoCast> and | 
| 2703 |  |  |  |  |  |  | L<::Sybase::ASE|DBIx::Class::Storage::DBI::Sybase::ASE>. | 
| 2704 |  |  |  |  |  |  |  | 
| 2705 |  |  |  |  |  |  | The default implementation returns C, implement in your Storage driver if | 
| 2706 |  |  |  |  |  |  | you need this functionality. | 
| 2707 |  |  |  |  |  |  |  | 
| 2708 |  |  |  |  |  |  | Should map types from other databases to the native RDBMS type, for example | 
| 2709 |  |  |  |  |  |  | C to C. | 
| 2710 |  |  |  |  |  |  |  | 
| 2711 |  |  |  |  |  |  | Types with modifiers should map to the underlying data type. For example, | 
| 2712 |  |  |  |  |  |  | C should become C. | 
| 2713 |  |  |  |  |  |  |  | 
| 2714 |  |  |  |  |  |  | Composite types should map to the container type, for example | 
| 2715 |  |  |  |  |  |  | C becomes C. | 
| 2716 |  |  |  |  |  |  |  | 
| 2717 |  |  |  |  |  |  | =cut | 
| 2718 |  |  |  |  |  |  |  | 
| 2719 |  |  |  |  |  |  | sub _native_data_type { | 
| 2720 |  |  |  |  |  |  | #my ($self, $data_type) = @_; | 
| 2721 |  |  |  |  |  |  | return undef | 
| 2722 | 0 |  |  | 0 |  | 0 | } | 
| 2723 |  |  |  |  |  |  |  | 
| 2724 |  |  |  |  |  |  | # Check if placeholders are supported at all | 
| 2725 |  |  |  |  |  |  | sub _determine_supports_placeholders { | 
| 2726 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 2727 | 0 |  |  |  |  | 0 | my $dbh  = $self->_get_dbh; | 
| 2728 |  |  |  |  |  |  |  | 
| 2729 |  |  |  |  |  |  | # some drivers provide a $dbh attribute (e.g. Sybase and $dbh->{syb_dynamic_supported}) | 
| 2730 |  |  |  |  |  |  | # but it is inaccurate more often than not | 
| 2731 |  |  |  |  |  |  | return try { | 
| 2732 | 0 |  |  | 0 |  | 0 | local $dbh->{PrintError} = 0; | 
| 2733 | 0 |  |  |  |  | 0 | local $dbh->{RaiseError} = 1; | 
| 2734 | 0 |  |  |  |  | 0 | $dbh->do('select ?', {}, 1); | 
| 2735 | 0 |  |  |  |  | 0 | 1; | 
| 2736 |  |  |  |  |  |  | } | 
| 2737 |  |  |  |  |  |  | catch { | 
| 2738 | 0 |  |  | 0 |  | 0 | 0; | 
| 2739 | 0 |  |  |  |  | 0 | }; | 
| 2740 |  |  |  |  |  |  | } | 
| 2741 |  |  |  |  |  |  |  | 
| 2742 |  |  |  |  |  |  | # Check if placeholders bound to non-string types throw exceptions | 
| 2743 |  |  |  |  |  |  | # | 
| 2744 |  |  |  |  |  |  | sub _determine_supports_typeless_placeholders { | 
| 2745 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 2746 | 0 |  |  |  |  | 0 | my $dbh  = $self->_get_dbh; | 
| 2747 |  |  |  |  |  |  |  | 
| 2748 |  |  |  |  |  |  | return try { | 
| 2749 | 0 |  |  | 0 |  | 0 | local $dbh->{PrintError} = 0; | 
| 2750 | 0 |  |  |  |  | 0 | local $dbh->{RaiseError} = 1; | 
| 2751 |  |  |  |  |  |  | # this specifically tests a bind that is NOT a string | 
| 2752 | 0 |  |  |  |  | 0 | $dbh->do('select 1 where 1 = ?', {}, 1); | 
| 2753 | 0 |  |  |  |  | 0 | 1; | 
| 2754 |  |  |  |  |  |  | } | 
| 2755 |  |  |  |  |  |  | catch { | 
| 2756 | 0 |  |  | 0 |  | 0 | 0; | 
| 2757 | 0 |  |  |  |  | 0 | }; | 
| 2758 |  |  |  |  |  |  | } | 
| 2759 |  |  |  |  |  |  |  | 
| 2760 |  |  |  |  |  |  | =head2 sqlt_type | 
| 2761 |  |  |  |  |  |  |  | 
| 2762 |  |  |  |  |  |  | Returns the database driver name. | 
| 2763 |  |  |  |  |  |  |  | 
| 2764 |  |  |  |  |  |  | =cut | 
| 2765 |  |  |  |  |  |  |  | 
| 2766 |  |  |  |  |  |  | sub sqlt_type { | 
| 2767 |  |  |  |  |  |  | shift->_get_dbh->{Driver}->{Name}; | 
| 2768 |  |  |  |  |  |  | } | 
| 2769 |  |  |  |  |  |  |  | 
| 2770 |  |  |  |  |  |  | =head2 bind_attribute_by_data_type | 
| 2771 |  |  |  |  |  |  |  | 
| 2772 |  |  |  |  |  |  | Given a datatype from column info, returns a database specific bind | 
| 2773 |  |  |  |  |  |  | attribute for C<< $dbh->bind_param($val,$attribute) >> or nothing if we will | 
| 2774 |  |  |  |  |  |  | let the database planner just handle it. | 
| 2775 |  |  |  |  |  |  |  | 
| 2776 |  |  |  |  |  |  | This method is always called after the driver has been determined and a DBI | 
| 2777 |  |  |  |  |  |  | connection has been established. Therefore you can refer to C | 
| 2778 |  |  |  |  |  |  | and/or C directly, without worrying about loading | 
| 2779 |  |  |  |  |  |  | the correct modules. | 
| 2780 |  |  |  |  |  |  |  | 
| 2781 |  |  |  |  |  |  | =cut | 
| 2782 |  |  |  |  |  |  |  | 
| 2783 |  |  |  |  |  |  | sub bind_attribute_by_data_type { | 
| 2784 | 2 |  |  | 2 | 1 | 13 | return; | 
| 2785 |  |  |  |  |  |  | } | 
| 2786 |  |  |  |  |  |  |  | 
| 2787 |  |  |  |  |  |  | =head2 is_datatype_numeric | 
| 2788 |  |  |  |  |  |  |  | 
| 2789 |  |  |  |  |  |  | Given a datatype from column_info, returns a boolean value indicating if | 
| 2790 |  |  |  |  |  |  | the current RDBMS considers it a numeric value. This controls how | 
| 2791 |  |  |  |  |  |  | L decides whether to mark the column as | 
| 2792 |  |  |  |  |  |  | dirty - when the datatype is deemed numeric a C<< != >> comparison will | 
| 2793 |  |  |  |  |  |  | be performed instead of the usual C. | 
| 2794 |  |  |  |  |  |  |  | 
| 2795 |  |  |  |  |  |  | =cut | 
| 2796 |  |  |  |  |  |  |  | 
| 2797 |  |  |  |  |  |  | sub is_datatype_numeric { | 
| 2798 |  |  |  |  |  |  | #my ($self, $dt) = @_; | 
| 2799 |  |  |  |  |  |  |  | 
| 2800 | 46 | 50 |  | 46 | 1 | 157 | return 0 unless $_[1]; | 
| 2801 |  |  |  |  |  |  |  | 
| 2802 | 46 |  |  |  |  | 400 | $_[1] =~ /^ (?: | 
| 2803 |  |  |  |  |  |  | numeric | int(?:eger)? | (?:tiny|small|medium|big)int | dec(?:imal)? | real | float | double (?: \s+ precision)? | (?:big)?serial | 
| 2804 |  |  |  |  |  |  | ) $/ix; | 
| 2805 |  |  |  |  |  |  | } | 
| 2806 |  |  |  |  |  |  |  | 
| 2807 |  |  |  |  |  |  |  | 
| 2808 |  |  |  |  |  |  | =head2 create_ddl_dir | 
| 2809 |  |  |  |  |  |  |  | 
| 2810 |  |  |  |  |  |  | =over 4 | 
| 2811 |  |  |  |  |  |  |  | 
| 2812 |  |  |  |  |  |  | =item Arguments: $schema, \@databases, $version, $directory, $preversion, \%sqlt_args | 
| 2813 |  |  |  |  |  |  |  | 
| 2814 |  |  |  |  |  |  | =back | 
| 2815 |  |  |  |  |  |  |  | 
| 2816 |  |  |  |  |  |  | Creates a SQL file based on the Schema, for each of the specified | 
| 2817 |  |  |  |  |  |  | database engines in C<\@databases> in the given directory. | 
| 2818 |  |  |  |  |  |  | (note: specify L names, not L driver names). | 
| 2819 |  |  |  |  |  |  |  | 
| 2820 |  |  |  |  |  |  | Given a previous version number, this will also create a file containing | 
| 2821 |  |  |  |  |  |  | the ALTER TABLE statements to transform the previous schema into the | 
| 2822 |  |  |  |  |  |  | current one. Note that these statements may contain C or | 
| 2823 |  |  |  |  |  |  | C statements that can potentially destroy data. | 
| 2824 |  |  |  |  |  |  |  | 
| 2825 |  |  |  |  |  |  | The file names are created using the C method below, please | 
| 2826 |  |  |  |  |  |  | override this method in your schema if you would like a different file | 
| 2827 |  |  |  |  |  |  | name format. For the ALTER file, the same format is used, replacing | 
| 2828 |  |  |  |  |  |  | $version in the name with "$preversion-$version". | 
| 2829 |  |  |  |  |  |  |  | 
| 2830 |  |  |  |  |  |  | See L for a list of values for C<\%sqlt_args>. | 
| 2831 |  |  |  |  |  |  | The most common value for this would be C<< { add_drop_table => 1 } >> | 
| 2832 |  |  |  |  |  |  | to have the SQL produced include a C statement for each table | 
| 2833 |  |  |  |  |  |  | created. For quoting purposes supply C. | 
| 2834 |  |  |  |  |  |  |  | 
| 2835 |  |  |  |  |  |  | If no arguments are passed, then the following default values are assumed: | 
| 2836 |  |  |  |  |  |  |  | 
| 2837 |  |  |  |  |  |  | =over 4 | 
| 2838 |  |  |  |  |  |  |  | 
| 2839 |  |  |  |  |  |  | =item databases  - ['MySQL', 'SQLite', 'PostgreSQL'] | 
| 2840 |  |  |  |  |  |  |  | 
| 2841 |  |  |  |  |  |  | =item version    - $schema->schema_version | 
| 2842 |  |  |  |  |  |  |  | 
| 2843 |  |  |  |  |  |  | =item directory  - './' | 
| 2844 |  |  |  |  |  |  |  | 
| 2845 |  |  |  |  |  |  | =item preversion - | 
| 2846 |  |  |  |  |  |  |  | 
| 2847 |  |  |  |  |  |  | =back | 
| 2848 |  |  |  |  |  |  |  | 
| 2849 |  |  |  |  |  |  | By default, C<\%sqlt_args> will have | 
| 2850 |  |  |  |  |  |  |  | 
| 2851 |  |  |  |  |  |  | { add_drop_table => 1, ignore_constraint_names => 1, ignore_index_names => 1 } | 
| 2852 |  |  |  |  |  |  |  | 
| 2853 |  |  |  |  |  |  | merged with the hash passed in. To disable any of those features, pass in a | 
| 2854 |  |  |  |  |  |  | hashref like the following | 
| 2855 |  |  |  |  |  |  |  | 
| 2856 |  |  |  |  |  |  | { ignore_constraint_names => 0, # ... other options } | 
| 2857 |  |  |  |  |  |  |  | 
| 2858 |  |  |  |  |  |  |  | 
| 2859 |  |  |  |  |  |  | WARNING: You are strongly advised to check all SQL files created, before applying | 
| 2860 |  |  |  |  |  |  | them. | 
| 2861 |  |  |  |  |  |  |  | 
| 2862 |  |  |  |  |  |  | =cut | 
| 2863 |  |  |  |  |  |  |  | 
| 2864 |  |  |  |  |  |  | sub create_ddl_dir { | 
| 2865 | 0 |  |  | 0 | 1 | 0 | my ($self, $schema, $databases, $version, $dir, $preversion, $sqltargs) = @_; | 
| 2866 |  |  |  |  |  |  |  | 
| 2867 | 0 | 0 |  |  |  | 0 | unless ($dir) { | 
| 2868 | 0 |  |  |  |  | 0 | carp "No directory given, using ./\n"; | 
| 2869 | 0 |  |  |  |  | 0 | $dir = './'; | 
| 2870 |  |  |  |  |  |  | } else { | 
| 2871 | 0 | 0 | 0 |  |  | 0 | -d $dir | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 2872 |  |  |  |  |  |  | or | 
| 2873 |  |  |  |  |  |  | (require File::Path and File::Path::mkpath (["$dir"]))  # mkpath does not like objects (i.e. Path::Class::Dir) | 
| 2874 |  |  |  |  |  |  | or | 
| 2875 |  |  |  |  |  |  | $self->throw_exception( | 
| 2876 |  |  |  |  |  |  | "Failed to create '$dir': " . ($! || $@ || 'error unknown') | 
| 2877 |  |  |  |  |  |  | ); | 
| 2878 |  |  |  |  |  |  | } | 
| 2879 |  |  |  |  |  |  |  | 
| 2880 | 0 | 0 |  |  |  | 0 | $self->throw_exception ("Directory '$dir' does not exist\n") unless(-d $dir); | 
| 2881 |  |  |  |  |  |  |  | 
| 2882 | 0 |  | 0 |  |  | 0 | $databases ||= ['MySQL', 'SQLite', 'PostgreSQL']; | 
| 2883 | 0 | 0 |  |  |  | 0 | $databases = [ $databases ] if(ref($databases) ne 'ARRAY'); | 
| 2884 |  |  |  |  |  |  |  | 
| 2885 | 0 |  | 0 |  |  | 0 | my $schema_version = $schema->schema_version || '1.x'; | 
| 2886 | 0 |  | 0 |  |  | 0 | $version ||= $schema_version; | 
| 2887 |  |  |  |  |  |  |  | 
| 2888 |  |  |  |  |  |  | $sqltargs = { | 
| 2889 |  |  |  |  |  |  | add_drop_table => 1, | 
| 2890 |  |  |  |  |  |  | ignore_constraint_names => 1, | 
| 2891 |  |  |  |  |  |  | ignore_index_names => 1, | 
| 2892 |  |  |  |  |  |  | quote_identifiers => $self->sql_maker->_quoting_enabled, | 
| 2893 | 0 | 0 |  |  |  | 0 | %{$sqltargs || {}} | 
|  | 0 |  |  |  |  | 0 |  | 
| 2894 |  |  |  |  |  |  | }; | 
| 2895 |  |  |  |  |  |  |  | 
| 2896 | 0 | 0 |  |  |  | 0 | unless (DBIx::Class::Optional::Dependencies->req_ok_for ('deploy')) { | 
| 2897 | 0 |  |  |  |  | 0 | $self->throw_exception("Can't create a ddl file without " . DBIx::Class::Optional::Dependencies->req_missing_for ('deploy') ); | 
| 2898 |  |  |  |  |  |  | } | 
| 2899 |  |  |  |  |  |  |  | 
| 2900 | 0 |  |  |  |  | 0 | my $sqlt = SQL::Translator->new( $sqltargs ); | 
| 2901 |  |  |  |  |  |  |  | 
| 2902 | 0 |  |  |  |  | 0 | $sqlt->parser('SQL::Translator::Parser::DBIx::Class'); | 
| 2903 | 0 | 0 |  |  |  | 0 | my $sqlt_schema = $sqlt->translate({ data => $schema }) | 
| 2904 |  |  |  |  |  |  | or $self->throw_exception ($sqlt->error); | 
| 2905 |  |  |  |  |  |  |  | 
| 2906 | 0 |  |  |  |  | 0 | foreach my $db (@$databases) { | 
| 2907 | 0 |  |  |  |  | 0 | $sqlt->reset(); | 
| 2908 | 0 |  |  |  |  | 0 | $sqlt->{schema} = $sqlt_schema; | 
| 2909 | 0 |  |  |  |  | 0 | $sqlt->producer($db); | 
| 2910 |  |  |  |  |  |  |  | 
| 2911 | 0 |  |  |  |  | 0 | my $file; | 
| 2912 | 0 |  |  |  |  | 0 | my $filename = $schema->ddl_filename($db, $version, $dir); | 
| 2913 | 0 | 0 | 0 |  |  | 0 | if (-e $filename && ($version eq $schema_version )) { | 
| 2914 |  |  |  |  |  |  | # if we are dumping the current version, overwrite the DDL | 
| 2915 | 0 |  |  |  |  | 0 | carp "Overwriting existing DDL file - $filename"; | 
| 2916 | 0 |  |  |  |  | 0 | unlink($filename); | 
| 2917 |  |  |  |  |  |  | } | 
| 2918 |  |  |  |  |  |  |  | 
| 2919 | 0 |  |  |  |  | 0 | my $output = $sqlt->translate; | 
| 2920 | 0 | 0 |  |  |  | 0 | if(!$output) { | 
| 2921 | 0 |  |  |  |  | 0 | carp("Failed to translate to $db, skipping. (" . $sqlt->error . ")"); | 
| 2922 | 0 |  |  |  |  | 0 | next; | 
| 2923 |  |  |  |  |  |  | } | 
| 2924 | 0 | 0 |  |  |  | 0 | if(!open($file, ">$filename")) { | 
| 2925 | 0 |  |  |  |  | 0 | $self->throw_exception("Can't open $filename for writing ($!)"); | 
| 2926 | 0 |  |  |  |  | 0 | next; | 
| 2927 |  |  |  |  |  |  | } | 
| 2928 | 0 |  |  |  |  | 0 | print $file $output; | 
| 2929 | 0 |  |  |  |  | 0 | close($file); | 
| 2930 |  |  |  |  |  |  |  | 
| 2931 | 0 | 0 |  |  |  | 0 | next unless ($preversion); | 
| 2932 |  |  |  |  |  |  |  | 
| 2933 | 0 |  |  |  |  | 0 | require SQL::Translator::Diff; | 
| 2934 |  |  |  |  |  |  |  | 
| 2935 | 0 |  |  |  |  | 0 | my $prefilename = $schema->ddl_filename($db, $preversion, $dir); | 
| 2936 | 0 | 0 |  |  |  | 0 | if(!-e $prefilename) { | 
| 2937 | 0 |  |  |  |  | 0 | carp("No previous schema file found ($prefilename)"); | 
| 2938 | 0 |  |  |  |  | 0 | next; | 
| 2939 |  |  |  |  |  |  | } | 
| 2940 |  |  |  |  |  |  |  | 
| 2941 | 0 |  |  |  |  | 0 | my $difffile = $schema->ddl_filename($db, $version, $dir, $preversion); | 
| 2942 | 0 | 0 |  |  |  | 0 | if(-e $difffile) { | 
| 2943 | 0 |  |  |  |  | 0 | carp("Overwriting existing diff file - $difffile"); | 
| 2944 | 0 |  |  |  |  | 0 | unlink($difffile); | 
| 2945 |  |  |  |  |  |  | } | 
| 2946 |  |  |  |  |  |  |  | 
| 2947 | 0 |  |  |  |  | 0 | my $source_schema; | 
| 2948 |  |  |  |  |  |  | { | 
| 2949 | 0 |  |  |  |  | 0 | my $t = SQL::Translator->new($sqltargs); | 
|  | 0 |  |  |  |  | 0 |  | 
| 2950 | 0 |  |  |  |  | 0 | $t->debug( 0 ); | 
| 2951 | 0 |  |  |  |  | 0 | $t->trace( 0 ); | 
| 2952 |  |  |  |  |  |  |  | 
| 2953 | 0 | 0 |  |  |  | 0 | $t->parser( $db ) | 
| 2954 |  |  |  |  |  |  | or $self->throw_exception ($t->error); | 
| 2955 |  |  |  |  |  |  |  | 
| 2956 | 0 | 0 |  |  |  | 0 | my $out = $t->translate( $prefilename ) | 
| 2957 |  |  |  |  |  |  | or $self->throw_exception ($t->error); | 
| 2958 |  |  |  |  |  |  |  | 
| 2959 | 0 |  |  |  |  | 0 | $source_schema = $t->schema; | 
| 2960 |  |  |  |  |  |  |  | 
| 2961 | 0 | 0 |  |  |  | 0 | $source_schema->name( $prefilename ) | 
| 2962 |  |  |  |  |  |  | unless ( $source_schema->name ); | 
| 2963 |  |  |  |  |  |  | } | 
| 2964 |  |  |  |  |  |  |  | 
| 2965 |  |  |  |  |  |  | # The "new" style of producers have sane normalization and can support | 
| 2966 |  |  |  |  |  |  | # diffing a SQL file against a DBIC->SQLT schema. Old style ones don't | 
| 2967 |  |  |  |  |  |  | # And we have to diff parsed SQL against parsed SQL. | 
| 2968 | 0 |  |  |  |  | 0 | my $dest_schema = $sqlt_schema; | 
| 2969 |  |  |  |  |  |  |  | 
| 2970 | 0 | 0 |  |  |  | 0 | unless ( "SQL::Translator::Producer::$db"->can('preprocess_schema') ) { | 
| 2971 | 0 |  |  |  |  | 0 | my $t = SQL::Translator->new($sqltargs); | 
| 2972 | 0 |  |  |  |  | 0 | $t->debug( 0 ); | 
| 2973 | 0 |  |  |  |  | 0 | $t->trace( 0 ); | 
| 2974 |  |  |  |  |  |  |  | 
| 2975 | 0 | 0 |  |  |  | 0 | $t->parser( $db ) | 
| 2976 |  |  |  |  |  |  | or $self->throw_exception ($t->error); | 
| 2977 |  |  |  |  |  |  |  | 
| 2978 | 0 | 0 |  |  |  | 0 | my $out = $t->translate( $filename ) | 
| 2979 |  |  |  |  |  |  | or $self->throw_exception ($t->error); | 
| 2980 |  |  |  |  |  |  |  | 
| 2981 | 0 |  |  |  |  | 0 | $dest_schema = $t->schema; | 
| 2982 |  |  |  |  |  |  |  | 
| 2983 | 0 | 0 |  |  |  | 0 | $dest_schema->name( $filename ) | 
| 2984 |  |  |  |  |  |  | unless $dest_schema->name; | 
| 2985 |  |  |  |  |  |  | } | 
| 2986 |  |  |  |  |  |  |  | 
| 2987 | 0 |  |  |  |  | 0 | my $diff = do { | 
| 2988 |  |  |  |  |  |  | # FIXME - this is a terrible workaround for | 
| 2989 |  |  |  |  |  |  | # https://github.com/dbsrgits/sql-translator/commit/2d23c1e | 
| 2990 |  |  |  |  |  |  | # Fixing it in this sloppy manner so that we don't hve to | 
| 2991 |  |  |  |  |  |  | # lockstep an SQLT release as well. Needs to be removed at | 
| 2992 |  |  |  |  |  |  | # some point, and SQLT dep bumped | 
| 2993 | 0 | 0 |  |  |  | 0 | local $SQL::Translator::Producer::SQLite::NO_QUOTES | 
| 2994 |  |  |  |  |  |  | if $SQL::Translator::Producer::SQLite::NO_QUOTES; | 
| 2995 |  |  |  |  |  |  |  | 
| 2996 | 0 |  |  |  |  | 0 | SQL::Translator::Diff::schema_diff($source_schema, $db, | 
| 2997 |  |  |  |  |  |  | $dest_schema,   $db, | 
| 2998 |  |  |  |  |  |  | $sqltargs | 
| 2999 |  |  |  |  |  |  | ); | 
| 3000 |  |  |  |  |  |  | }; | 
| 3001 |  |  |  |  |  |  |  | 
| 3002 | 0 | 0 |  |  |  | 0 | if(!open $file, ">$difffile") { | 
| 3003 | 0 |  |  |  |  | 0 | $self->throw_exception("Can't write to $difffile ($!)"); | 
| 3004 | 0 |  |  |  |  | 0 | next; | 
| 3005 |  |  |  |  |  |  | } | 
| 3006 | 0 |  |  |  |  | 0 | print $file $diff; | 
| 3007 | 0 |  |  |  |  | 0 | close($file); | 
| 3008 |  |  |  |  |  |  | } | 
| 3009 |  |  |  |  |  |  | } | 
| 3010 |  |  |  |  |  |  |  | 
| 3011 |  |  |  |  |  |  | =head2 deployment_statements | 
| 3012 |  |  |  |  |  |  |  | 
| 3013 |  |  |  |  |  |  | =over 4 | 
| 3014 |  |  |  |  |  |  |  | 
| 3015 |  |  |  |  |  |  | =item Arguments: $schema, $type, $version, $directory, $sqlt_args | 
| 3016 |  |  |  |  |  |  |  | 
| 3017 |  |  |  |  |  |  | =back | 
| 3018 |  |  |  |  |  |  |  | 
| 3019 |  |  |  |  |  |  | Returns the statements used by L | 
| 3020 |  |  |  |  |  |  | and L. | 
| 3021 |  |  |  |  |  |  |  | 
| 3022 |  |  |  |  |  |  | The L (not L) database driver name can be explicitly | 
| 3023 |  |  |  |  |  |  | provided in C<$type>, otherwise the result of L is used as default. | 
| 3024 |  |  |  |  |  |  |  | 
| 3025 |  |  |  |  |  |  | C<$directory> is used to return statements from files in a previously created | 
| 3026 |  |  |  |  |  |  | L directory and is optional. The filenames are constructed | 
| 3027 |  |  |  |  |  |  | from L, the schema name and the C<$version>. | 
| 3028 |  |  |  |  |  |  |  | 
| 3029 |  |  |  |  |  |  | If no C<$directory> is specified then the statements are constructed on the | 
| 3030 |  |  |  |  |  |  | fly using L and C<$version> is ignored. | 
| 3031 |  |  |  |  |  |  |  | 
| 3032 |  |  |  |  |  |  | See L for a list of values for C<$sqlt_args>. | 
| 3033 |  |  |  |  |  |  |  | 
| 3034 |  |  |  |  |  |  | =cut | 
| 3035 |  |  |  |  |  |  |  | 
| 3036 |  |  |  |  |  |  | sub deployment_statements { | 
| 3037 |  |  |  |  |  |  | my ($self, $schema, $type, $version, $dir, $sqltargs) = @_; | 
| 3038 |  |  |  |  |  |  | $type ||= $self->sqlt_type; | 
| 3039 |  |  |  |  |  |  | $version ||= $schema->schema_version || '1.x'; | 
| 3040 |  |  |  |  |  |  | $dir ||= './'; | 
| 3041 |  |  |  |  |  |  | my $filename = $schema->ddl_filename($type, $version, $dir); | 
| 3042 |  |  |  |  |  |  | if(-f $filename) | 
| 3043 |  |  |  |  |  |  | { | 
| 3044 |  |  |  |  |  |  | # FIXME replace this block when a proper sane sql parser is available | 
| 3045 |  |  |  |  |  |  | my $file; | 
| 3046 |  |  |  |  |  |  | open($file, "<$filename") | 
| 3047 |  |  |  |  |  |  | or $self->throw_exception("Can't open $filename ($!)"); | 
| 3048 |  |  |  |  |  |  | my @rows = <$file>; | 
| 3049 |  |  |  |  |  |  | close($file); | 
| 3050 |  |  |  |  |  |  | return join('', @rows); | 
| 3051 |  |  |  |  |  |  | } | 
| 3052 |  |  |  |  |  |  |  | 
| 3053 |  |  |  |  |  |  | unless (DBIx::Class::Optional::Dependencies->req_ok_for ('deploy') ) { | 
| 3054 |  |  |  |  |  |  | $self->throw_exception("Can't deploy without a ddl_dir or " . DBIx::Class::Optional::Dependencies->req_missing_for ('deploy') ); | 
| 3055 |  |  |  |  |  |  | } | 
| 3056 |  |  |  |  |  |  |  | 
| 3057 |  |  |  |  |  |  | # sources needs to be a parser arg, but for simplicity allow at top level | 
| 3058 |  |  |  |  |  |  | # coming in | 
| 3059 |  |  |  |  |  |  | $sqltargs->{parser_args}{sources} = delete $sqltargs->{sources} | 
| 3060 |  |  |  |  |  |  | if exists $sqltargs->{sources}; | 
| 3061 |  |  |  |  |  |  |  | 
| 3062 |  |  |  |  |  |  | $sqltargs->{quote_identifiers} = $self->sql_maker->_quoting_enabled | 
| 3063 |  |  |  |  |  |  | unless exists $sqltargs->{quote_identifiers}; | 
| 3064 |  |  |  |  |  |  |  | 
| 3065 |  |  |  |  |  |  | my $tr = SQL::Translator->new( | 
| 3066 |  |  |  |  |  |  | producer => "SQL::Translator::Producer::${type}", | 
| 3067 |  |  |  |  |  |  | %$sqltargs, | 
| 3068 |  |  |  |  |  |  | parser => 'SQL::Translator::Parser::DBIx::Class', | 
| 3069 |  |  |  |  |  |  | data => $schema, | 
| 3070 |  |  |  |  |  |  | ); | 
| 3071 |  |  |  |  |  |  |  | 
| 3072 |  |  |  |  |  |  | return preserve_context { | 
| 3073 |  |  |  |  |  |  | $tr->translate | 
| 3074 |  |  |  |  |  |  | } after => sub { | 
| 3075 |  |  |  |  |  |  | $self->throw_exception( 'Unable to produce deployment statements: ' . $tr->error) | 
| 3076 |  |  |  |  |  |  | unless defined $_[0]; | 
| 3077 |  |  |  |  |  |  | }; | 
| 3078 |  |  |  |  |  |  | } | 
| 3079 |  |  |  |  |  |  |  | 
| 3080 |  |  |  |  |  |  | # FIXME deploy() currently does not accurately report sql errors | 
| 3081 |  |  |  |  |  |  | # Will always return true while errors are warned | 
| 3082 |  |  |  |  |  |  | sub deploy { | 
| 3083 | 0 |  |  | 0 | 1 | 0 | my ($self, $schema, $type, $sqltargs, $dir) = @_; | 
| 3084 |  |  |  |  |  |  | my $deploy = sub { | 
| 3085 | 0 |  |  | 0 |  | 0 | my $line = shift; | 
| 3086 | 0 | 0 |  |  |  | 0 | return if(!$line); | 
| 3087 | 0 | 0 |  |  |  | 0 | return if($line =~ /^--/); | 
| 3088 |  |  |  |  |  |  | # next if($line =~ /^DROP/m); | 
| 3089 | 0 | 0 |  |  |  | 0 | return if($line =~ /^BEGIN TRANSACTION/m); | 
| 3090 | 0 | 0 |  |  |  | 0 | return if($line =~ /^COMMIT/m); | 
| 3091 | 0 | 0 |  |  |  | 0 | return if $line =~ /^\s+$/; # skip whitespace only | 
| 3092 | 0 |  |  |  |  | 0 | $self->_query_start($line); | 
| 3093 |  |  |  |  |  |  | try { | 
| 3094 |  |  |  |  |  |  | # do a dbh_do cycle here, as we need some error checking in | 
| 3095 |  |  |  |  |  |  | # place (even though we will ignore errors) | 
| 3096 | 0 |  |  |  |  | 0 | $self->dbh_do (sub { $_[1]->do($line) }); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3097 |  |  |  |  |  |  | } catch { | 
| 3098 | 0 |  |  |  |  | 0 | carp qq{$_ (running "${line}")}; | 
| 3099 | 0 |  |  |  |  | 0 | }; | 
| 3100 | 0 |  |  |  |  | 0 | $self->_query_end($line); | 
| 3101 | 0 |  |  |  |  | 0 | }; | 
| 3102 | 0 | 0 |  |  |  | 0 | my @statements = $schema->deployment_statements($type, undef, $dir, { %{ $sqltargs || {} }, no_comments => 1 } ); | 
|  | 0 |  |  |  |  | 0 |  | 
| 3103 | 0 | 0 |  |  |  | 0 | if (@statements > 1) { | 
|  |  | 0 |  |  |  |  |  | 
| 3104 | 0 |  |  |  |  | 0 | foreach my $statement (@statements) { | 
| 3105 | 0 |  |  |  |  | 0 | $deploy->( $statement ); | 
| 3106 |  |  |  |  |  |  | } | 
| 3107 |  |  |  |  |  |  | } | 
| 3108 |  |  |  |  |  |  | elsif (@statements == 1) { | 
| 3109 |  |  |  |  |  |  | # split on single line comments and end of statements | 
| 3110 | 0 |  |  |  |  | 0 | foreach my $line ( split(/\s*--.*\n|;\n/, $statements[0])) { | 
| 3111 | 0 |  |  |  |  | 0 | $deploy->( $line ); | 
| 3112 |  |  |  |  |  |  | } | 
| 3113 |  |  |  |  |  |  | } | 
| 3114 |  |  |  |  |  |  | } | 
| 3115 |  |  |  |  |  |  |  | 
| 3116 |  |  |  |  |  |  | =head2 datetime_parser | 
| 3117 |  |  |  |  |  |  |  | 
| 3118 |  |  |  |  |  |  | Returns the datetime parser class | 
| 3119 |  |  |  |  |  |  |  | 
| 3120 |  |  |  |  |  |  | =cut | 
| 3121 |  |  |  |  |  |  |  | 
| 3122 |  |  |  |  |  |  | sub datetime_parser { | 
| 3123 | 1 |  |  | 1 | 1 | 17 | my $self = shift; | 
| 3124 | 1 |  | 33 |  |  | 4 | return $self->{datetime_parser} ||= do { | 
| 3125 | 1 |  |  |  |  | 7 | $self->build_datetime_parser(@_); | 
| 3126 |  |  |  |  |  |  | }; | 
| 3127 |  |  |  |  |  |  | } | 
| 3128 |  |  |  |  |  |  |  | 
| 3129 |  |  |  |  |  |  | =head2 datetime_parser_type | 
| 3130 |  |  |  |  |  |  |  | 
| 3131 |  |  |  |  |  |  | Defines the datetime parser class - currently defaults to L | 
| 3132 |  |  |  |  |  |  |  | 
| 3133 |  |  |  |  |  |  | =head2 build_datetime_parser | 
| 3134 |  |  |  |  |  |  |  | 
| 3135 |  |  |  |  |  |  | See L | 
| 3136 |  |  |  |  |  |  |  | 
| 3137 |  |  |  |  |  |  | =cut | 
| 3138 |  |  |  |  |  |  |  | 
| 3139 |  |  |  |  |  |  | sub build_datetime_parser { | 
| 3140 |  |  |  |  |  |  | my $self = shift; | 
| 3141 |  |  |  |  |  |  | my $type = $self->datetime_parser_type(@_); | 
| 3142 |  |  |  |  |  |  | return $type; | 
| 3143 |  |  |  |  |  |  | } | 
| 3144 |  |  |  |  |  |  |  | 
| 3145 |  |  |  |  |  |  |  | 
| 3146 |  |  |  |  |  |  | =head2 is_replicating | 
| 3147 |  |  |  |  |  |  |  | 
| 3148 |  |  |  |  |  |  | A boolean that reports if a particular L is set to | 
| 3149 |  |  |  |  |  |  | replicate from a master database.  Default is undef, which is the result | 
| 3150 |  |  |  |  |  |  | returned by databases that don't support replication. | 
| 3151 |  |  |  |  |  |  |  | 
| 3152 |  |  |  |  |  |  | =cut | 
| 3153 |  |  |  |  |  |  |  | 
| 3154 |  |  |  |  |  |  | sub is_replicating { | 
| 3155 | 0 |  |  | 0 | 1 | 0 | return; | 
| 3156 |  |  |  |  |  |  |  | 
| 3157 |  |  |  |  |  |  | } | 
| 3158 |  |  |  |  |  |  |  | 
| 3159 |  |  |  |  |  |  | =head2 lag_behind_master | 
| 3160 |  |  |  |  |  |  |  | 
| 3161 |  |  |  |  |  |  | Returns a number that represents a certain amount of lag behind a master db | 
| 3162 |  |  |  |  |  |  | when a given storage is replicating.  The number is database dependent, but | 
| 3163 |  |  |  |  |  |  | starts at zero and increases with the amount of lag. Default in undef | 
| 3164 |  |  |  |  |  |  |  | 
| 3165 |  |  |  |  |  |  | =cut | 
| 3166 |  |  |  |  |  |  |  | 
| 3167 |  |  |  |  |  |  | sub lag_behind_master { | 
| 3168 | 0 |  |  | 0 | 1 | 0 | return; | 
| 3169 |  |  |  |  |  |  | } | 
| 3170 |  |  |  |  |  |  |  | 
| 3171 |  |  |  |  |  |  | =head2 relname_to_table_alias | 
| 3172 |  |  |  |  |  |  |  | 
| 3173 |  |  |  |  |  |  | =over 4 | 
| 3174 |  |  |  |  |  |  |  | 
| 3175 |  |  |  |  |  |  | =item Arguments: $relname, $join_count | 
| 3176 |  |  |  |  |  |  |  | 
| 3177 |  |  |  |  |  |  | =item Return Value: $alias | 
| 3178 |  |  |  |  |  |  |  | 
| 3179 |  |  |  |  |  |  | =back | 
| 3180 |  |  |  |  |  |  |  | 
| 3181 |  |  |  |  |  |  | L uses L names as table aliases in | 
| 3182 |  |  |  |  |  |  | queries. | 
| 3183 |  |  |  |  |  |  |  | 
| 3184 |  |  |  |  |  |  | This hook is to allow specific L drivers to change the | 
| 3185 |  |  |  |  |  |  | way these aliases are named. | 
| 3186 |  |  |  |  |  |  |  | 
| 3187 |  |  |  |  |  |  | The default behavior is C<< "$relname_$join_count" if $join_count > 1 >>, | 
| 3188 |  |  |  |  |  |  | otherwise C<"$relname">. | 
| 3189 |  |  |  |  |  |  |  | 
| 3190 |  |  |  |  |  |  | =cut | 
| 3191 |  |  |  |  |  |  |  | 
| 3192 |  |  |  |  |  |  | sub relname_to_table_alias { | 
| 3193 | 1649 |  |  | 1649 | 1 | 27114 | my ($self, $relname, $join_count) = @_; | 
| 3194 |  |  |  |  |  |  |  | 
| 3195 | 1649 | 100 | 100 |  |  | 5313 | my $alias = ($join_count && $join_count > 1 ? | 
| 3196 |  |  |  |  |  |  | join('_', $relname, $join_count) : $relname); | 
| 3197 |  |  |  |  |  |  |  | 
| 3198 | 1649 |  |  |  |  | 3584 | return $alias; | 
| 3199 |  |  |  |  |  |  | } | 
| 3200 |  |  |  |  |  |  |  | 
| 3201 |  |  |  |  |  |  | # The size in bytes to use for DBI's ->bind_param_inout, this is the generic | 
| 3202 |  |  |  |  |  |  | # version and it may be necessary to amend or override it for a specific storage | 
| 3203 |  |  |  |  |  |  | # if such binds are necessary. | 
| 3204 |  |  |  |  |  |  | sub _max_column_bytesize { | 
| 3205 | 0 |  |  | 0 |  |  | my ($self, $attr) = @_; | 
| 3206 |  |  |  |  |  |  |  | 
| 3207 | 0 |  |  |  |  |  | my $max_size; | 
| 3208 |  |  |  |  |  |  |  | 
| 3209 | 0 | 0 |  |  |  |  | if ($attr->{sqlt_datatype}) { | 
| 3210 | 0 |  |  |  |  |  | my $data_type = lc($attr->{sqlt_datatype}); | 
| 3211 |  |  |  |  |  |  |  | 
| 3212 | 0 | 0 |  |  |  |  | if ($attr->{sqlt_size}) { | 
| 3213 |  |  |  |  |  |  |  | 
| 3214 |  |  |  |  |  |  | # String/sized-binary types | 
| 3215 | 0 | 0 |  |  |  |  | if ($data_type =~ /^(?: | 
|  |  | 0 |  |  |  |  |  | 
| 3216 |  |  |  |  |  |  | l? (?:var)? char(?:acter)? (?:\s*varying)? | 
| 3217 |  |  |  |  |  |  | | | 
| 3218 |  |  |  |  |  |  | (?:var)? binary (?:\s*varying)? | 
| 3219 |  |  |  |  |  |  | | | 
| 3220 |  |  |  |  |  |  | raw | 
| 3221 |  |  |  |  |  |  | )\b/x | 
| 3222 |  |  |  |  |  |  | ) { | 
| 3223 | 0 |  |  |  |  |  | $max_size = $attr->{sqlt_size}; | 
| 3224 |  |  |  |  |  |  | } | 
| 3225 |  |  |  |  |  |  | # Other charset/unicode types, assume scale of 4 | 
| 3226 |  |  |  |  |  |  | elsif ($data_type =~ /^(?: | 
| 3227 |  |  |  |  |  |  | national \s* character (?:\s*varying)? | 
| 3228 |  |  |  |  |  |  | | | 
| 3229 |  |  |  |  |  |  | nchar | 
| 3230 |  |  |  |  |  |  | | | 
| 3231 |  |  |  |  |  |  | univarchar | 
| 3232 |  |  |  |  |  |  | | | 
| 3233 |  |  |  |  |  |  | nvarchar | 
| 3234 |  |  |  |  |  |  | )\b/x | 
| 3235 |  |  |  |  |  |  | ) { | 
| 3236 | 0 |  |  |  |  |  | $max_size = $attr->{sqlt_size} * 4; | 
| 3237 |  |  |  |  |  |  | } | 
| 3238 |  |  |  |  |  |  | } | 
| 3239 |  |  |  |  |  |  |  | 
| 3240 | 0 | 0 | 0 |  |  |  | if (!$max_size and !$self->_is_lob_type($data_type)) { | 
| 3241 | 0 |  |  |  |  |  | $max_size = 100 # for all other (numeric?) datatypes | 
| 3242 |  |  |  |  |  |  | } | 
| 3243 |  |  |  |  |  |  | } | 
| 3244 |  |  |  |  |  |  |  | 
| 3245 | 0 | 0 | 0 |  |  |  | $max_size || $self->_dbic_connect_attributes->{LongReadLen} || $self->_get_dbh->{LongReadLen} || 8000; | 
|  |  |  | 0 |  |  |  |  | 
| 3246 |  |  |  |  |  |  | } | 
| 3247 |  |  |  |  |  |  |  | 
| 3248 |  |  |  |  |  |  | # Determine if a data_type is some type of BLOB | 
| 3249 |  |  |  |  |  |  | sub _is_lob_type { | 
| 3250 | 0 |  |  | 0 |  |  | my ($self, $data_type) = @_; | 
| 3251 | 0 | 0 | 0 |  |  |  | $data_type && ($data_type =~ /lob|bfile|text|image|bytea|memo/i | 
| 3252 |  |  |  |  |  |  | || $data_type =~ /^long(?:\s+(?:raw|bit\s*varying|varbit|binary | 
| 3253 |  |  |  |  |  |  | |varchar|character\s*varying|nvarchar | 
| 3254 |  |  |  |  |  |  | |national\s*character\s*varying))?\z/xi); | 
| 3255 |  |  |  |  |  |  | } | 
| 3256 |  |  |  |  |  |  |  | 
| 3257 |  |  |  |  |  |  | sub _is_binary_lob_type { | 
| 3258 | 0 |  |  | 0 |  |  | my ($self, $data_type) = @_; | 
| 3259 | 0 | 0 | 0 |  |  |  | $data_type && ($data_type =~ /blob|bfile|image|bytea/i | 
| 3260 |  |  |  |  |  |  | || $data_type =~ /^long(?:\s+(?:raw|bit\s*varying|varbit|binary))?\z/xi); | 
| 3261 |  |  |  |  |  |  | } | 
| 3262 |  |  |  |  |  |  |  | 
| 3263 |  |  |  |  |  |  | sub _is_text_lob_type { | 
| 3264 | 0 |  |  | 0 |  |  | my ($self, $data_type) = @_; | 
| 3265 | 0 | 0 | 0 |  |  |  | $data_type && ($data_type =~ /^(?:clob|memo)\z/i | 
| 3266 |  |  |  |  |  |  | || $data_type =~ /^long(?:\s+(?:varchar|character\s*varying|nvarchar | 
| 3267 |  |  |  |  |  |  | |national\s*character\s*varying))\z/xi); | 
| 3268 |  |  |  |  |  |  | } | 
| 3269 |  |  |  |  |  |  |  | 
| 3270 |  |  |  |  |  |  | # Determine if a data_type is some type of a binary type | 
| 3271 |  |  |  |  |  |  | sub _is_binary_type { | 
| 3272 | 0 |  |  | 0 |  |  | my ($self, $data_type) = @_; | 
| 3273 | 0 | 0 | 0 |  |  |  | $data_type && ($self->_is_binary_lob_type($data_type) | 
| 3274 |  |  |  |  |  |  | || $data_type =~ /(?:var)?(?:binary|bit|graphic)(?:\s*varying)?/i); | 
| 3275 |  |  |  |  |  |  | } | 
| 3276 |  |  |  |  |  |  |  | 
| 3277 |  |  |  |  |  |  | 1; | 
| 3278 |  |  |  |  |  |  |  | 
| 3279 |  |  |  |  |  |  | =head1 USAGE NOTES | 
| 3280 |  |  |  |  |  |  |  | 
| 3281 |  |  |  |  |  |  | =head2 DBIx::Class and AutoCommit | 
| 3282 |  |  |  |  |  |  |  | 
| 3283 |  |  |  |  |  |  | DBIx::Class can do some wonderful magic with handling exceptions, | 
| 3284 |  |  |  |  |  |  | disconnections, and transactions when you use C<< AutoCommit => 1 >> | 
| 3285 |  |  |  |  |  |  | (the default) combined with L for | 
| 3286 |  |  |  |  |  |  | transaction support. | 
| 3287 |  |  |  |  |  |  |  | 
| 3288 |  |  |  |  |  |  | If you set C<< AutoCommit => 0 >> in your connect info, then you are always | 
| 3289 |  |  |  |  |  |  | in an assumed transaction between commits, and you're telling us you'd | 
| 3290 |  |  |  |  |  |  | like to manage that manually.  A lot of the magic protections offered by | 
| 3291 |  |  |  |  |  |  | this module will go away.  We can't protect you from exceptions due to database | 
| 3292 |  |  |  |  |  |  | disconnects because we don't know anything about how to restart your | 
| 3293 |  |  |  |  |  |  | transactions.  You're on your own for handling all sorts of exceptional | 
| 3294 |  |  |  |  |  |  | cases if you choose the C<< AutoCommit => 0 >> path, just as you would | 
| 3295 |  |  |  |  |  |  | be with raw DBI. | 
| 3296 |  |  |  |  |  |  |  | 
| 3297 |  |  |  |  |  |  | =head1 FURTHER QUESTIONS? | 
| 3298 |  |  |  |  |  |  |  | 
| 3299 |  |  |  |  |  |  | Check the list of L. | 
| 3300 |  |  |  |  |  |  |  | 
| 3301 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 3302 |  |  |  |  |  |  |  | 
| 3303 |  |  |  |  |  |  | This module is free software L | 
| 3304 |  |  |  |  |  |  | by the L. You can | 
| 3305 |  |  |  |  |  |  | redistribute it and/or modify it under the same terms as the | 
| 3306 |  |  |  |  |  |  | L. |