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