File Coverage

blib/lib/Teng.pm
Criterion Covered Total %
statement 333 375 88.8
branch 123 172 71.5
condition 47 72 65.2
subroutine 54 57 94.7
pod 32 33 96.9
total 589 709 83.0


line stmt bran cond sub pod time code
1             package Teng;
2 68     68   3558851 use strict;
  68         172  
  68         1555  
3 68     68   316 use warnings;
  68         120  
  68         1252  
4 68     68   291 use Carp ();
  68         119  
  68         1173  
5 68     68   24304 use Class::Load 0.06 ();
  68         1045270  
  68         1805  
6 68     68   73710 use DBI 1.33;
  68         816146  
  68         3492  
7 68     68   517 use Scalar::Util;
  68         132  
  68         2238  
8 68     68   27992 use SQL::Maker::SQLType qw(sql_type);
  68         22044  
  68         3054  
9 68     68   23186 use Teng::Row;
  68         172  
  68         2059  
10 68     68   21121 use Teng::Iterator;
  68         177  
  68         1688  
11 68     68   20268 use Teng::Schema;
  68         171  
  68         1804  
12 68     68   24139 use DBIx::TransactionManager 1.06;
  68         47316  
  68         1509  
13 68     68   19990 use Teng::QueryBuilder;
  68         248  
  68         2795  
14             use Class::Accessor::Lite 0.05
15 68         526 rw => [ qw(
16             connect_info
17             on_connect_do
18             schema
19             schema_class
20             suppress_row_objects
21             sql_builder
22             sql_comment
23             owner_pid
24             no_ping
25             fields_case
26             apply_sql_types
27             guess_sql_types
28             )]
29 68     68   445 ;
  68         1130  
30              
31             our $VERSION = '0.30';
32              
33             sub load_plugin {
34 65     65 1 33493 my ($class, $pkg, $opt) = @_;
35 65 100       391 $pkg = $pkg =~ s/^\+// ? $pkg : "Teng::Plugin::$pkg";
36 65         268 Class::Load::load_class($pkg);
37              
38 65 50       2754 $class = ref($class) if ref($class);
39              
40 65   100     483 my $alias = delete $opt->{alias} || +{};
41             {
42 68     68   15557 no strict 'refs';
  68         142  
  68         212616  
  65         159  
43 65         118 for my $method ( @{"${pkg}::EXPORT"} ){
  65         319  
44 67   66     575 *{$class . '::' . ($alias->{$method} || $method)} = $pkg->can($method);
  67         646  
45             }
46             }
47              
48 65 100       764 $pkg->init($class, $opt) if $pkg->can('init');
49             }
50              
51             sub new {
52 90     90 1 569291 my $class = shift;
53 90 100       521 my %args = @_ == 1 ? %{$_[0]} : @_;
  76         389  
54 90         277 my $loader = delete $args{loader};
55              
56 90 100       402 if ( my $mode = delete $args{mode} ) {
57 2         153 warn "IMPORTANT: 'mode' option is DEPRECATED AND *WILL* BE REMOVED. PLEASE USE 'no_ping' option.\n";
58 2 50       14 if ( !exists $args{no_ping} ) {
59 2 100       12 $args{no_ping} = $mode eq 'ping' ? 0 : 1;
60             }
61             }
62              
63 90         932 my $self = bless {
64             schema_class => "$class\::Schema",
65             owner_pid => $$,
66             no_ping => 0,
67             fields_case => 'NAME_lc',
68             boolean_value => {true => 1, false => 0},
69             %args,
70             }, $class;
71              
72 90 100 66     853 if (!$loader && ! $self->schema) {
73 85         837 my $schema_class = $self->{schema_class};
74 85         444 Class::Load::load_class( $schema_class );
75 85         8350 my $schema = $schema_class->instance;
76 85 50       588 if (! $schema) {
77 0         0 Carp::croak("schema object was not passed, and could not get schema instance from $schema_class");
78             }
79 85         531 $schema->namespace($class);
80 85         726 $self->schema( $schema );
81             }
82              
83 90 50 66     893 unless ($self->connect_info || $self->{dbh}) {
84 0         0 Carp::croak("'dbh' or 'connect_info' is required.");
85             }
86              
87 90 100       1065 if ( ! $self->{dbh} ) {
88 20         92 $self->connect;
89             } else {
90 70         413 $self->_prepare_from_dbh;
91             }
92              
93 88         1976 return $self;
94             }
95              
96             sub set_boolean_value {
97 1     1 1 1776 my $self = shift;
98 1 50       4 if (@_) {
99 1         3 my ($true, $false) = @_;
100 1         4 $self->{boolean_value} = {true => $true, false => $false};
101             }
102 1         4 return $self->{boolean_value};
103             }
104              
105             sub mode {
106 0     0 1 0 my $self = shift;
107 0         0 warn "IMPORTANT: 'mode' option is DEPRECATED AND *WILL* BE REMOVED. PLEASE USE 'no_ping' option.\n";
108              
109 0 0       0 if ( @_ ) {
110 0         0 my $mode = shift;
111 0 0       0 if ( $mode eq 'ping' ) {
112 0         0 $self->no_ping(0);
113             }
114             else {
115 0         0 $self->no_ping(1);
116             }
117             }
118              
119 0 0       0 return $self->no_ping ? 'no_ping' : 'ping';
120             }
121              
122             # forcefully connect
123             sub connect {
124 28     28 1 5326 my ($self, @args) = @_;
125              
126 28         132 $self->in_transaction_check;
127              
128 26 50       86 if (@args) {
129 0         0 $self->connect_info( \@args );
130             }
131 26         73 my $connect_info = $self->connect_info;
132             $connect_info->[3] = {
133             # basic defaults
134             AutoCommit => 1,
135             PrintError => 0,
136             RaiseError => 1,
137 26 100       108 %{ $connect_info->[3] || {} },
  26         185  
138             };
139              
140 26 100 33     67 $self->{dbh} = eval { DBI->connect(@$connect_info) }
  26         139  
141             or Carp::croak("Connection error: " . ($@ || $DBI::errstr));
142 25         83574 delete $self->{txn_manager};
143              
144 25         152 $self->owner_pid($$);
145              
146 25         229 $self->_on_connect_do;
147 24         175 $self->_prepare_from_dbh;
148             }
149              
150             sub _on_connect_do {
151 74     74   132 my $self = shift;
152              
153 74 100       271 if ( my $on_connect_do = $self->on_connect_do ) {
154 17 100       201 if (not ref($on_connect_do)) {
    100          
    100          
155 4         15 $self->do($on_connect_do);
156             } elsif (ref($on_connect_do) eq 'CODE') {
157 8         26 $on_connect_do->($self);
158             } elsif (ref($on_connect_do) eq 'ARRAY') {
159 4         18 $self->do($_) for @$on_connect_do;
160             } else {
161 1         92 Carp::croak('Invalid on_connect_do: '.ref($on_connect_do));
162             }
163             }
164             }
165              
166             sub reconnect {
167 58     58 1 304157 my $self = shift;
168              
169 58         290 $self->in_transaction_check;
170              
171 50         253 my $dbh = $self->{dbh};
172              
173 50         238 $self->disconnect();
174              
175 50 50       389 if ( @_ ) {
176 0         0 $self->connect(@_);
177             }
178             else {
179             # Why don't use $dbh->clone({InactiveDestroy => 0}) ?
180             # because, DBI v1.616 clone with \%attr has bug.
181             # my $dbh2 = $dbh->clone({});
182             # my $dbh3 = $dbh2->clone({});
183             # $dbh2 is ok, but $dbh3 is undef.
184             # ---
185             # Don't assign $self-{dbh} directry.
186             # Because if $self->{dbh} is undef then reconnect fail always.
187             # https://github.com/nekokak/p5-Teng/pull/98
188 50 100 33     118 my $new_dbh = eval { $dbh->clone }
  50         437  
189             or Carp::croak("ReConnection error: " . ($@ || $DBI::errstr));
190 49         23687 $self->{dbh} = $new_dbh;
191 49         224 $self->{dbh}->{InactiveDestroy} = 0;
192              
193 49         207 $self->owner_pid($$);
194 49         416 $self->_on_connect_do;
195 49         450 $self->_prepare_from_dbh;
196             }
197             }
198              
199             sub disconnect {
200 52     52 1 3509 my $self = shift;
201              
202 52         145 delete $self->{txn_manager};
203 52 50       223 if ( my $dbh = $self->{dbh} ) {
204 52 100 100     255 if ( $self->owner_pid && ($self->owner_pid != $$) ) {
205 3         416 $dbh->{InactiveDestroy} = 1;
206             }
207             else {
208 49         3286 $dbh->disconnect;
209             }
210             }
211 52         302 $self->owner_pid(undef);
212             }
213              
214             sub _prepare_from_dbh {
215 143     143   290 my $self = shift;
216              
217 143         2063 $self->{driver_name} = $self->{dbh}->{Driver}->{Name};
218 143         476 my $builder = $self->{sql_builder};
219 143 100       496 if (! $builder ) {
220 88   100     732 my $sql_builder_class = $self->{sql_builder_class} || 'Teng::QueryBuilder';
221             $builder = $sql_builder_class->new(
222             driver => $self->{driver_name},
223 88 100       249 %{ $self->{sql_builder_args} || {} }
  88         1408  
224             );
225 88         2761 $self->sql_builder( $builder );
226             }
227 143         1177 $self->{dbh}->{FetchHashKeyName} = $self->{fields_case};
228              
229 143 100       1079 $self->{schema}->prepare_from_dbh($self->{dbh}) if $self->{schema};
230             }
231              
232             sub _verify_pid {
233 714     714   1084 my $self = shift;
234              
235 714 100 66     1888 if ( !$self->owner_pid || $self->owner_pid != $$ ) {
    50          
236 1         183 $self->reconnect;
237             }
238             elsif ( my $dbh = $self->{dbh} ) {
239 713 50 100     12881 if ( !$dbh->FETCH('Active') ) {
    100          
240 0         0 $self->reconnect;
241             }
242             elsif ( !$self->no_ping && !$dbh->ping) {
243 12         810 $self->reconnect;
244             }
245             }
246             }
247              
248             sub dbh {
249 647     647 1 23971 my $self = shift;
250              
251 647         1779 $self->_verify_pid;
252 643         18089 $self->{dbh};
253             }
254              
255             sub connected {
256 0     0 1 0 my $self = shift;
257 0         0 my $dbh = $self->{dbh};
258 0   0     0 return $self->owner_pid && $dbh->ping;
259             }
260              
261             sub _execute {
262 1     1   5431 my $self = shift;
263 1         7 warn "IMPORTANT: '_execute' method is DEPRECATED AND *WILL* BE REMOVED. PLEASE USE 'execute' method.\n";
264 1         5 return $self->execute(@_);
265             }
266              
267             our $SQL_COMMENT_LEVEL = 0;
268             sub execute {
269 408     408 1 3955 my ($self, $sql, $binds) = @_;
270              
271 408 100 66     2069 if ($ENV{TENG_SQL_COMMENT} || $self->sql_comment) {
272 1         2 my $i = $SQL_COMMENT_LEVEL; # optimize, as we would *NEVER* be called
273 1         9 while ( my (@caller) = caller($i++) ) {
274 1 50       11 next if ( $caller[0]->isa( __PACKAGE__ ) );
275 1 50       4 next if $caller[0] =~ /^Teng::/; # skip Teng::Row, Teng::Plugin::* etc.
276 1         4 my $comment = "$caller[1] at line $caller[2]";
277 1         3 $comment =~ s/\*\// /g;
278 1         4 $sql = "/* $comment */\n$sql";
279 1         3 last;
280             }
281             }
282              
283 408         2605 my $sth;
284 408         717 eval {
285 408         983 $sth = $self->dbh->prepare($sql);
286 402         35513 my $i = 1;
287 402 100       693 for my $v ( @{ $binds || [] } ) {
  402         1615  
288 588 100 100     11413 if (Scalar::Util::blessed($v) && ref($v) eq 'SQL::Maker::SQLType') {
289 326         590 $sth->bind_param($i++, ${$v->value_ref}, $v->type);
  326         978  
290             } else {
291             # allow array ref for using pg_types. e.g. [ $value => { pg_type => PG_BYTEA } ]
292             # ref. https://metacpan.org/pod/DBD::Pg#quote
293 262 50       3642 $sth->bind_param( $i++, ref($v) eq 'ARRAY' ? @$v : $v );
294             }
295             }
296 402         250445 $sth->execute();
297             };
298              
299 408 100       4160 if ($@) {
300 12         68 $self->handle_error($sql, $binds, $@);
301             }
302              
303             # When the return value is never used, should finish statement handler
304 396 100       1045 unless (defined wantarray) {
305 2         15 $sth->finish();
306 2         21 return;
307             }
308              
309 394         1317 return $sth;
310             }
311              
312             sub _last_insert_id {
313 27     27   89 my ($self, $table_name, $column) = @_;
314              
315 27         59 my $driver = $self->{driver_name};
316 27 50       144 if ( $driver eq 'mysql' ) {
    50          
    50          
    0          
317 0         0 return $self->{dbh}->{mysql_insertid};
318             } elsif ( $driver eq 'Pg' ) {
319 0 0       0 if (defined $column) {
320 0         0 return $self->dbh->last_insert_id( undef, undef, undef, undef,{ sequence => join( '_', $table_name, $column, 'seq' ) } );
321             } else {
322 0         0 return $self->dbh->last_insert_id( undef, undef, $table_name, undef);
323             }
324             } elsif ( $driver eq 'SQLite' ) {
325 27         79 return $self->dbh->func('last_insert_rowid');
326             } elsif ( $driver eq 'Oracle' ) {
327 0         0 return;
328             } else {
329 0         0 Carp::croak "Don't know how to get last insert id for $driver";
330             }
331             }
332              
333             sub _bind_sql_type_to_args {
334 192     192   427 my ( $self, $table, $args ) = @_;
335 192         370 my $bind_args = {};
336              
337 192         330 for my $col (keys %{$args}) {
  192         494  
338             # if $args->{$col} is a ref, it is scalar ref or already
339             # sql type bined parameter. so ignored.
340 336 100       4126 $bind_args->{$col} = ref $args->{$col} ? $args->{$col} : sql_type(\$args->{$col}, $table->get_sql_type($col));
341             }
342              
343 192         3063 return $bind_args;
344             }
345              
346             sub do_insert {
347 166     166 1 394 my ($self, $table_name, $args, $prefix) = @_;
348              
349 166   50     936 $prefix ||= 'INSERT INTO';
350 166         593 my $table = $self->schema->get_table($table_name);
351 166 100       521 if (! $table) {
352 1         3 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
353 1         133 Carp::croak( "Table definition for $table_name does not exist (Did you declare it in our schema?)" );
354             }
355              
356 165         296 for my $col (keys %{$args}) {
  165         635  
357 304         1108 $args->{$col} = $table->call_deflate($col, $args->{$col});
358             }
359 165         687 my $bind_args = $self->_bind_sql_type_to_args( $table, $args );
360 165         1032 my ($sql, @binds) = $self->{sql_builder}->insert( $table_name, $bind_args, { prefix => $prefix } );
361 165         27695 $self->execute($sql, \@binds);
362             }
363              
364             sub fast_insert {
365 7     7 1 13016 my ($self, $table_name, $args, $prefix) = @_;
366              
367 7         23 my $sth = $self->do_insert($table_name, $args, $prefix);
368              
369             # XXX in MySQL 5.7.8 or later, $self->dbh->{mysql_insertid} will always return 0,
370             # so that get mysql_insertid from $sth. (https://bugs.mysql.com/bug.php?id=78778)
371 7 100       73 return $sth->{mysql_insertid} if defined $sth->{mysql_insertid};
372              
373             # XXX in Pg, _last_insert_id has potential failure when inserting to non Serial table or explicitly inserting Serrial id
374 6         30 $self->_last_insert_id($table_name);
375             }
376              
377             sub insert {
378 161     161 1 736302 my ($self, $table_name, $args, $prefix) = @_;
379              
380 161         648 my $sth = $self->do_insert($table_name, $args, $prefix);
381 149 100       1962 return unless defined wantarray;
382              
383 53         6481 my $table = $self->schema->get_table($table_name);
384 53         296 my $pk = $table->primary_keys();
385              
386 53         345 my @missing_primary_keys = grep { not defined $args->{$_} } @$pk;
  62         294  
387 53 100       209 if (@missing_primary_keys == 1) {
388             # XXX in MySQL 5.7.8 or later, $self->dbh->{mysql_insertid} will always return 0,
389             # so that get mysql_insertid from $sth. (https://bugs.mysql.com/bug.php?id=78778)
390             $args->{$missing_primary_keys[0]} = defined $sth->{mysql_insertid} ? $sth->{mysql_insertid}
391 22 100       365 : $self->_last_insert_id($table_name, $missing_primary_keys[0]);
392             }
393              
394 53 100       318 return $args if $self->suppress_row_objects;
395              
396 51         298 my %where;
397 51         100 my $refetch = 1;
398 51         158 for my $key (@$pk) {
399 60 50       268 if (ref $args->{$key}) {
400             # care references. eg. \'NOW()'
401 0         0 $refetch = undef;
402 0         0 last;
403             }
404 60         177 $where{$key} = $args->{$key};
405             }
406 51 50 33     363 if (%where && $refetch) {
407             # refetch the row for cleanup scalar refs and fill default values
408 51         302 return $self->single($table_name, \%where);
409             }
410              
411             $table->row_class->new(
412             {
413 0         0 row_data => $args,
414             teng => $self,
415             table_name => $table_name,
416             }
417             );
418             }
419              
420             sub bulk_insert {
421 2     2 1 3509 my ($self, $table_name, $args, $opt) = @_;
422              
423 2 50       4 return unless scalar(@{$args||[]});
  2 50       12  
424              
425 2         6 my $dbh = $self->dbh;
426             my $can_multi_insert = $dbh->{Driver}->{Name} eq 'mysql' ? 1
427             : $dbh->{Driver}->{Name} eq 'Pg'
428 2 50 33     30 && $dbh->{ pg_server_version } >= 82000 ? 1
    50          
429             : 0;
430              
431 2 50       9 if ($can_multi_insert) {
432 0         0 my $table = $self->schema->get_table($table_name);
433 0 0       0 if (! $table) {
434 0         0 Carp::croak( "Table definition for $table_name does not exist (Did you declare it in our schema?)" );
435             }
436              
437 0 0       0 if ( $table->has_deflators ) {
438 0         0 for my $row (@$args) {
439 0         0 for my $col (keys %{$row}) {
  0         0  
440 0         0 $row->{$col} = $table->call_deflate($col, $row->{$col});
441             }
442             }
443             }
444              
445 0         0 my ($sql, @binds) = $self->sql_builder->insert_multi( $table_name, $args, $opt );
446 0         0 $self->execute($sql, \@binds);
447             } else {
448             # use transaction for better performance and atomicity.
449 2         14 my $txn = $self->txn_scope();
450 2         143 for my $arg (@$args) {
451             # do not run trigger for consistency with mysql.
452 6         31 $self->insert($table_name, $arg, $opt->{prefix});
453             }
454 2         12 $txn->commit;
455             }
456             }
457              
458             sub do_update {
459 27     27 1 66 my ($self, $table_name, $args, $where) = @_;
460              
461 27         108 my ($sql, @binds) = $self->{sql_builder}->update( $table_name, $args, $where );
462 27         5802 my $sth = $self->execute($sql, \@binds);
463 27         126 my $rows = $sth->rows;
464 27         92 $sth->finish;
465              
466 27         323 $rows;
467             }
468              
469             sub update {
470 8     8 1 3723 my ($self, $table_name, $args, $where) = @_;
471              
472 8         27 my $table = $self->schema->get_table($table_name);
473 8 100       24 if (! $table) {
474 1         81 Carp::croak( "Table definition for $table_name does not exist (Did you declare it in our schema?)" );
475             }
476              
477 7         12 for my $col (keys %{$args}) {
  7         27  
478 9         51 $args->{$col} = $table->call_deflate($col, $args->{$col});
479             }
480            
481 7         27 $self->do_update($table_name, $self->_bind_sql_type_to_args( $table, $args ), $where);
482             }
483              
484             sub delete {
485 17     17 1 5028 my ($self, $table_name, $where) = @_;
486              
487 17         86 my ($sql, @binds) = $self->{sql_builder}->delete( $table_name, $where );
488 17         2690 my $sth = $self->execute($sql, \@binds);
489 17         110 my $rows = $sth->rows;
490 17         70 $sth->finish;
491              
492 17         275 $rows;
493             }
494              
495             #--------------------------------------------------------------------------------
496             # for transaction
497             sub txn_manager {
498 67     67 1 120 my $self = shift;
499 67         183 $self->_verify_pid;
500             $self->{txn_manager} ||= ($self->{txn_manager_class})
501 65 50 66     1527 ? $self->{txn_manager_class}->new($self->dbh)
502             : DBIx::TransactionManager->new($self->dbh);
503             }
504              
505             sub in_transaction_check {
506 86     86 0 162 my $self = shift;
507              
508 86 100       352 return unless $self->{txn_manager};
509              
510 31 100       115 if ( my $info = $self->{txn_manager}->in_transaction ) {
511 10         82 my $caller = $info->{caller};
512 10         104 my $pid = $info->{pid};
513 10         1442 Carp::confess("Detected transaction during a connect operation (last known transaction at $caller->[1] line $caller->[2], pid $pid). Refusing to proceed at");
514             }
515             }
516              
517             sub txn_scope {
518 19     19 1 9289 my $self = shift;
519 19         82 my @caller = caller();
520              
521 19         77 $self->txn_manager->txn_scope(caller => \@caller);
522             }
523              
524             sub txn_begin {
525 24     24 1 14803 my $self = shift;
526              
527 24         100 $self->txn_manager->txn_begin;
528             }
529 12     12 1 6662 sub txn_rollback { $_[0]->txn_manager->txn_rollback }
530 12     12 1 906 sub txn_commit { $_[0]->txn_manager->txn_commit }
531 0     0 1 0 sub txn_end { $_[0]->txn_manager->txn_end }
532              
533             #--------------------------------------------------------------------------------
534              
535             sub do {
536 21     21 1 10159 my ($self, $sql, $attr, @bind_vars) = @_;
537 21         43 my $ret;
538 21         43 eval { $ret = $self->dbh->do($sql, $attr, @bind_vars) };
  21         94  
539 21 100       69210 if ($@) {
540 1 50       10 $self->handle_error($sql, @bind_vars ? \@bind_vars : '', $@);
541             }
542 20         82 $ret;
543             }
544              
545             sub _get_select_columns {
546 171     171   370 my ($self, $table, $opt) = @_;
547              
548             return $opt->{'+columns'}
549 4         15 ? [@{$table->{escaped_columns}{$self->{driver_name}}}, @{$opt->{'+columns'}}]
  4         19  
550             : ($opt->{columns} || $table->{escaped_columns}{$self->{driver_name}})
551 171 100 66     1678 ;
552             }
553              
554             sub search {
555 35     35 1 40529 my ($self, $table_name, $where, $opt) = @_;
556              
557 35         146 my $table = $self->{schema}->get_table( $table_name );
558 35 100       99 if (! $table) {
559 1         138 Carp::croak("No such table $table_name");
560             }
561              
562             my ($sql, @binds) = $self->{sql_builder}->select(
563 34         136 $table_name,
564             $self->_get_select_columns($table, $opt),
565             $where,
566             $opt
567             );
568              
569 34         12796 $self->search_by_sql($sql, \@binds, $table_name);
570             }
571              
572             sub _bind_named {
573 5     5   13 my ($self, $sql, $args ) = @_;
574              
575 5         7 my @bind;
576 5         39 $sql =~ s{:([A-Za-z_][A-Za-z0-9_]*)}{
577 7 100       161 Carp::croak("'$1' does not exist in bind hash") if !exists $args->{$1};
578 6 100 66     25 if ( ref $args->{$1} && ref $args->{$1} eq "ARRAY" ) {
579 1         3 push @bind, @{ $args->{$1} };
  1         3  
580 1         3 my $tmp = join ',', map { '?' } @{ $args->{$1} };
  3         7  
  1         4  
581 1         5 "( $tmp )";
582             } else {
583 5         14 push @bind, $args->{$1};
584 5         18 '?'
585             }
586             }ge;
587              
588 4         40 return ($sql, \@bind);
589             }
590              
591             sub search_named {
592 4     4 1 7211 my ($self, $sql, $args, $table_name) = @_;
593              
594 4         19 $self->search_by_sql($self->_bind_named($sql, $args), $table_name);
595             }
596              
597             sub single {
598 131     131 1 1989222 my ($self, $table_name, $where, $opt) = @_;
599              
600 131         389 $opt->{limit} = 1;
601              
602 131         546 my $table = $self->{schema}->get_table( $table_name );
603 131 50       442 Carp::croak("No such table $table_name") unless $table;
604              
605             my ($sql, @binds) = $self->{sql_builder}->select(
606 131         582 $table_name,
607             $self->_get_select_columns($table, $opt),
608             $where,
609             $opt
610             );
611 131         64128 my $sth = $self->execute($sql, \@binds);
612              
613             # When the return value is never used, should not create row object
614             # case example: use `FOR UPDATE` query for global locking
615 131 50       372 unless (defined wantarray) {
616 0         0 $sth->finish();
617 0         0 return;
618             }
619              
620 131         4323 my $row = $sth->fetchrow_hashref($self->{fields_case});
621              
622 131 100       866 return undef unless $row; ## no critic
623 115 50       404 return $row if $self->{suppress_row_objects};
624              
625             $table->{row_class}->new(
626             {
627 115         1151 sql => $sql,
628             row_data => $row,
629             teng => $self,
630             table => $table,
631             table_name => $table_name,
632             }
633             );
634             }
635              
636             sub search_by_sql {
637 56     56 1 24687 my ($self, $sql, $bind, $table_name) = @_;
638              
639 56   100     264 $table_name ||= $self->_guess_table_name( $sql );
640 56         229 my $sth = $self->execute($sql, $bind);
641              
642             # When the return value is never used, should not create iterator object
643             # case example: use `FOR UPDATE` query for global locking
644 55 50       182 unless (defined wantarray) {
645 0         0 $sth->finish();
646 0         0 return;
647             }
648              
649             my $itr = Teng::Iterator->new(
650             teng => $self,
651             sth => $sth,
652             sql => $sql,
653             row_class => $self->{schema}->get_row_class($table_name),
654             table => $self->{schema}->get_table( $table_name ),
655             table_name => $table_name,
656             apply_sql_types => $self->{apply_sql_types} || $self->{guess_sql_types},
657             guess_sql_types => $self->{guess_sql_types},
658             suppress_object_creation => $self->{suppress_row_objects},
659 55   66     330 );
660 55 100       291 return wantarray ? $itr->all : $itr;
661             }
662              
663             sub single_by_sql {
664 2     2 1 1144 my ($self, $sql, $bind, $table_name) = @_;
665              
666 2   33     11 $table_name ||= $self->_guess_table_name( $sql );
667 2         8 my $table = $self->{schema}->get_table( $table_name );
668 2 50       7 Carp::croak("No such table $table_name") unless $table;
669              
670 2         11 my $sth = $self->execute($sql, $bind);
671              
672             # When the return value is never used, should not create row object
673             # case example: use `FOR UPDATE` query for global locking
674 2 50       9 unless (defined wantarray) {
675 0         0 $sth->finish();
676 0         0 return;
677             }
678              
679 2         78 my $row = $sth->fetchrow_hashref($self->{fields_case});
680              
681 2 50       11 return unless $row;
682 2 50       7 return $row if $self->{suppress_row_objects};
683              
684             $table->{row_class}->new(
685             {
686 2         35 sql => $sql,
687             row_data => $row,
688             teng => $self,
689             table => $table,
690             table_name => $table_name,
691             }
692             );
693             }
694              
695             sub new_row_from_hash {
696 4     4 1 2507 my ($self, $table_name, $data, $sql) = @_;
697              
698 4         15 my $table = $self->{schema}->get_table( $table_name );
699 4 50       8 Carp::croak("No such table $table_name") unless $table;
700              
701 4 50       10 return $data if $self->{suppress_row_objects};
702              
703             $table->{row_class}->new(
704             {
705 4   66     13 sql => $sql || do {
706             my @caller = caller(0);
707             my $level = 0;
708             while ($caller[0] eq __PACKAGE__ || $caller[0] eq ref $self) {
709             @caller = caller(++$level);
710             }
711             sprintf '/* DUMMY QUERY %s->new_row_from_hash created from %s line %d */', ref $self, $caller[1], $caller[2];
712             },
713             row_data => $data,
714             teng => $self,
715             table => $table,
716             table_name => $table_name,
717             }
718             );
719             }
720              
721             sub single_named {
722 1     1 1 1056 my ($self, $sql, $args, $table_name) = @_;
723              
724 1         8 $self->single_by_sql($self->_bind_named($sql, $args), $table_name);
725             }
726              
727             sub _guess_table_name {
728 27     27   1214 my ($class, $sql) = @_;
729              
730 27 100       231 if ($sql =~ /\sfrom\s+["`]?([\w]+)["`]?\s*/si) {
731 26         153 return $1;
732             }
733 1         4 return;
734             }
735              
736             sub handle_error {
737 13     13 1 47 my ($self, $stmt, $bind, $reason) = @_;
738 13         4313 require Data::Dumper;
739              
740 13         32678 local $Data::Dumper::Maxdepth = 2;
741 13         70 $stmt =~ s/\n/\n /gm;
742 13         57 Carp::croak sprintf <<"TRACE", $reason, $stmt, Data::Dumper::Dumper($bind);
743             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
744             @@@@@ Teng 's Exception @@@@@
745             Reason : %s
746             SQL : %s
747             BIND : %s
748             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
749             TRACE
750             }
751              
752             sub DESTROY {
753 87     87   114755 my $self = shift;
754              
755 87 100 100     441 if ( $self->owner_pid and $self->owner_pid != $$ and my $dbh = $self->{dbh} ) {
      66        
756 1         108 $dbh->{InactiveDestroy} = 1;
757             }
758             }
759              
760             1;
761              
762             __END__
763             =head1 NAME
764              
765             Teng - very simple DBI wrapper/ORMapper
766              
767             =head1 SYNOPSIS
768              
769             my $db = MyDB->new({ connect_info => [ 'dbi:SQLite:' ] });
770             my $row = $db->insert( 'table' => {
771             col1 => $value
772             } );
773              
774             =head1 DESCRIPTION
775              
776             Teng is very simple DBI wrapper and simple O/R Mapper.
777             It aims to be lightweight, with minimal dependencies so it's easier to install.
778              
779             =head1 BASIC USAGE
780              
781             create your db model base class.
782              
783             package Your::Model;
784             use parent 'Teng';
785             1;
786            
787             create your db schema class.
788             See Teng::Schema for docs on defining schema class.
789              
790             package Your::Model::Schema;
791             use Teng::Schema::Declare;
792             table {
793             name 'user';
794             pk 'id';
795             columns qw( foo bar baz );
796             };
797             1;
798            
799             in your script.
800              
801             use Your::Model;
802            
803             my $teng = Your::Model->new(\%args);
804             # insert new record.
805             my $row = $teng->insert('user',
806             {
807             id => 1,
808             }
809             );
810             $row->update({name => 'nekokak'}); # same do { $row->name('nekokak'); $row->update; }
811              
812             $row = $teng->single_by_sql(q{SELECT id, name FROM user WHERE id = ?}, [ 1 ]);
813             $row->delete();
814              
815             =head1 ARCHITECTURE
816              
817             Teng classes are comprised of three distinct components:
818              
819             =head2 MODEL
820              
821             The C<model> is where you say
822              
823             package MyApp::Model;
824             use parent 'Teng';
825              
826             This is the entry point to using Teng. You connect, insert, update, delete, select stuff using this object.
827              
828             =head2 SCHEMA
829              
830             The C<schema> is a simple class that describes your table definitions. Note that this is different from DBIx::Class terms.
831             DBIC's schema is equivalent to Teng's model + schema, where the actual schema information is scattered across the result classes.
832              
833             In Teng, you simply use Teng::Schema's domain specific language to define a set of tables
834              
835             package MyApp::Model::Schema;
836             use Teng::Schema::Declare;
837              
838             table {
839             name $table_name;
840             pk $primary_key_column;
841             columns qw(
842             column1
843             column2
844             column3
845             );
846             }
847              
848             ... and other tables ...
849              
850             =head2 ROW
851              
852             Unlike DBIx::Class, you don't need to have a set of classes that represent a row type (i.e. "result" classes in DBIC terms).
853             In Teng, the row objects are blessed into anonymous classes that inherit from Teng::Row,
854             so you don't have to create these classes if you just want to use some simple queries.
855              
856             If you want to define methods to be performed by your row objects, simply create a row class like so:
857              
858             package MyApp::Model::Row::Camelizedtable_name;
859             use parent qw(Teng::Row);
860              
861             Note that your table name will be camelized.
862              
863             =head1 METHODS
864              
865             Teng provides a number of methods to all your classes,
866              
867             =over
868              
869             =item $teng = Teng->new(\%args)
870              
871             Creates a new Teng instance.
872              
873             # connect new database connection.
874             my $db = Your::Model->new(
875             connect_info => [ $dsn, $username, $password, \%connect_options ]
876             );
877              
878             Arguments can be:
879              
880             =over
881              
882             =item * C<connect_info>
883              
884             Specifies the information required to connect to the database.
885             The argument should be a reference to a array in the form:
886              
887             [ $dsn, $user, $password, \%options ]
888              
889             You must pass C<connect_info> or C<dbh> to the constructor.
890              
891             =item * C<dbh>
892              
893             Specifies the database handle to use.
894              
895             =item * C<no_ping>
896              
897             By default, ping before each executing query.
898             If it affect performance then you can set to true for ping stopping.
899              
900             =item * C<fields_case>
901              
902             specific DBI.pm's FetchHashKeyName.
903              
904             =item * C<schema>
905              
906             Specifies the Teng::Schema instance to use.
907             If not specified, the value specified in C<schema_class> is loaded and
908             instantiated for you.
909              
910             =item * C<schema_class>
911              
912             Specifies the schema class to use.
913             By default {YOUR_MODEL_CLASS}::Schema is used.
914              
915             =item * C<txn_manager_class>
916              
917             Specifies the transaction manager class.
918             By default DBIx::TransactionManager is used.
919              
920             =item * C<suppress_row_objects>
921              
922             Specifies the row object creation mode. By default this value is C<false>.
923             If you specifies this to a C<true> value, no row object will be created when
924             a C<SELECT> statement is issued..
925              
926             =item * C<sql_builder>
927              
928             Speficies the SQL builder object. By default SQL::Maker is used, and as such,
929             if you provide your own SQL builder the interface needs to be compatible
930             with SQL::Maker.
931              
932             =item * C<sql_builder_class> : Str
933              
934             Speficies the SQL builder class name. By default SQL::Maker is used, and as such,
935             if you provide your own SQL builder the interface needs to be compatible
936             with SQL::Maker.
937              
938             Specified C<sql_builder_class> is instantiated with following:
939              
940             $sql_builder_class->new(
941             driver => $teng->{driver_name},
942             %{ $teng->{sql_builder_args} }
943             )
944              
945             This is not used when C<sql_builder> is specified.
946              
947             =item * C<sql_builder_args> : HashRef
948              
949             Speficies the arguments for constructor of C<sql_builder_class>. This is not used when C<sql_builder> is specified.
950              
951             =back
952              
953             =item C<$row = $teng-E<gt>insert($table_name, \%row_data)>
954              
955             Inserts a new record. Returns the inserted row object.
956              
957             my $row = $teng->insert('user',{
958             id => 1,
959             name => 'nekokak',
960             });
961              
962             If a primary key is available, it will be fetched after the insert -- so
963             an INSERT followed by SELECT is performed. If you do not want this, use
964             C<fast_insert>.
965              
966             =item C<$last_insert_id = $teng-E<gt>fast_insert($table_name, \%row_data);>
967              
968             insert new record and get last_insert_id.
969              
970             no creation row object.
971              
972             =item C<< $teng->do_insert >>
973              
974             Internal method called from C<insert> and C<fast_insert>. You can hook it on your responsibility.
975              
976             =item C<$teng-E<gt>bulk_insert($table_name, \@rows_data, \%opt)>
977              
978             Accepts either an arrayref of hashrefs.
979             each hashref should be a structure suitable
980             for submitting to a Your::Model->insert(...) method.
981             The second argument is an arrayref of hashrefs. All of the keys in these hashrefs must be exactly the same.
982              
983             insert many record by bulk.
984              
985             example:
986              
987             Your::Model->bulk_insert('user',[
988             {
989             id => 1,
990             name => 'nekokak',
991             },
992             {
993             id => 2,
994             name => 'yappo',
995             },
996             {
997             id => 3,
998             name => 'walf443',
999             },
1000             ]);
1001              
1002             You can specify C<$opt> like C<< { prefix => 'INSERT IGNORE INTO' } >> or C<< { update => { name => 'updated' } } >> optionally, which will be passed to query builder.
1003              
1004             =item C<$update_row_count = $teng-E<gt>update($table_name, \%update_row_data, [\%update_condition])>
1005              
1006             Calls UPDATE on C<$table_name>, with values specified in C<%update_ro_data>, and returns the number of rows updated. You may optionally specify C<%update_condition> to create a conditional update query.
1007              
1008             my $update_row_count = $teng->update('user',
1009             {
1010             name => 'nomaneko',
1011             },
1012             {
1013             id => 1
1014             }
1015             );
1016             # Executes UPDATE user SET name = 'nomaneko' WHERE id = 1
1017              
1018             You can also call update on a row object:
1019              
1020             my $row = $teng->single('user',{id => 1});
1021             $row->update({name => 'nomaneko'});
1022              
1023             You can use the set_column method:
1024              
1025             my $row = $teng->single('user', {id => 1});
1026             $row->set_column( name => 'yappo' );
1027             $row->update;
1028              
1029             you can column update by using column method:
1030              
1031             my $row = $teng->single('user', {id => 1});
1032             $row->name('yappo');
1033             $row->update;
1034              
1035             =item C<$updated_row_count = $teng-E<gt>do_update($table_name, \%set, \%where)>
1036              
1037             This is low level API for UPDATE. Normally, you should use update method instead of this.
1038              
1039             This method does not deflate \%args.
1040              
1041             =item C<$delete_row_count = $teng-E<gt>delete($table, \%delete_condition)>
1042              
1043             Deletes the specified record(s) from C<$table> and returns the number of rows deleted. You may optionally specify C<%delete_condition> to create a conditional delete query.
1044              
1045             my $rows_deleted = $teng->delete( 'user', {
1046             id => 1
1047             } );
1048             # Executes DELETE FROM user WHERE id = 1
1049              
1050             You can also call delete on a row object:
1051              
1052             my $row = $teng->single('user', {id => 1});
1053             $row->delete
1054              
1055             =item C<$itr = $teng-E<gt>search($table_name, [\%search_condition, [\%search_attr]])>
1056              
1057             simple search method.
1058             search method get Teng::Iterator's instance object.
1059              
1060             see L<Teng::Iterator>
1061              
1062             get iterator:
1063              
1064             my $itr = $teng->search('user',{id => 1},{order_by => 'id'});
1065              
1066             get rows:
1067              
1068             my @rows = $teng->search('user',{id => 1},{order_by => 'id'});
1069              
1070             =item C<$row = $teng-E<gt>single($table_name, \%search_condition)>
1071              
1072             get one record.
1073             give back one case of the beginning when it is acquired plural records by single method.
1074              
1075             my $row = $teng->single('user',{id =>1});
1076              
1077             =item C<$row = $teng-E<gt>new_row_from_hash($table_name, \%row_data, [$sql])>
1078              
1079             create row object from data. (not fetch from db.)
1080             It's useful in such as testing.
1081              
1082             my $row = $teng->new_row_from_hash('user', { id => 1, foo => "bar" });
1083             say $row->foo; # say bar
1084              
1085             =item C<$itr = $teng-E<gt>search_named($sql, [\%bind_values, [$table_name]])>
1086              
1087             execute named query
1088              
1089             my $itr = $teng->search_named(q{SELECT * FROM user WHERE id = :id}, {id => 1});
1090              
1091             If you give ArrayRef to value, that is expanded to "(?,?,?,?)" in SQL.
1092             It's useful in case use IN statement.
1093              
1094             # SELECT * FROM user WHERE id IN (?,?,?);
1095             # bind [1,2,3]
1096             my $itr = $teng->search_named(q{SELECT * FROM user WHERE id IN :ids}, {ids => [1, 2, 3]});
1097              
1098             If you give table_name. It is assumed the hint that makes Teng::Row's Object.
1099              
1100             =item C<$itr = $teng-E<gt>search_by_sql($sql, [\@bind_values, [$table_name]])>
1101              
1102             execute your SQL
1103              
1104             my $itr = $teng->search_by_sql(q{
1105             SELECT
1106             id, name
1107             FROM
1108             user
1109             WHERE
1110             id = ?
1111             },[ 1 ]);
1112              
1113             If $table is specified, it set table information to result iterator.
1114             So, you can use table row class to search_by_sql result.
1115              
1116             =item C<$row = $teng-E<gt>single_by_sql($sql, [\@bind_values, [$table_name]])>
1117              
1118             get one record from your SQL.
1119              
1120             my $row = $teng->single_by_sql(q{SELECT id,name FROM user WHERE id = ? LIMIT 1}, [1], 'user');
1121              
1122             This is a shortcut for
1123              
1124             my $row = $teng->search_by_sql(q{SELECT id,name FROM user WHERE id = ? LIMIT 1}, [1], 'user')->next;
1125              
1126             But optimized implementation.
1127              
1128             =item C<$row = $teng-E<gt>single_named($sql, [\%bind_values, [$table_name]])>
1129              
1130             get one record from execute named query
1131              
1132             my $row = $teng->single_named(q{SELECT id,name FROM user WHERE id = :id LIMIT 1}, {id => 1}, 'user');
1133              
1134             This is a shortcut for
1135              
1136             my $row = $teng->search_named(q{SELECT id,name FROM user WHERE id = :id LIMIT 1}, {id => 1}, 'user')->next;
1137              
1138             But optimized implementation.
1139              
1140             =item C<$sth = $teng-E<gt>execute($sql, [\@bind_values])>
1141              
1142             execute query and get statement handler.
1143             and will be inserted caller's file and line as a comment in the SQL if $ENV{TENG_SQL_COMMENT} or sql_comment is true value.
1144              
1145             =item C<$teng-E<gt>txn_scope>
1146              
1147             Creates a new transaction scope guard object.
1148              
1149             do {
1150             my $txn = $teng->txn_scope;
1151              
1152             $row->update({foo => 'bar'});
1153              
1154             $txn->commit;
1155             }
1156              
1157             If an exception occurs, or the guard object otherwise leaves the scope
1158             before C<< $txn->commit >> is called, the transaction will be rolled
1159             back by an explicit L</txn_rollback> call. In essence this is akin to
1160             using a L</txn_begin>/L</txn_commit> pair, without having to worry
1161             about calling L</txn_rollback> at the right places. Note that since there
1162             is no defined code closure, there will be no retries and other magic upon
1163             database disconnection.
1164              
1165             =item C<$txn_manager = $teng-E<gt>txn_manager>
1166              
1167             Create the transaction manager instance with specified C<txn_manager_class>.
1168              
1169             =item C<$teng-E<gt>txn_begin>
1170              
1171             start new transaction.
1172              
1173             =item C<$teng-E<gt>txn_commit>
1174              
1175             commit transaction.
1176              
1177             =item C<$teng-E<gt>txn_rollback>
1178              
1179             rollback transaction.
1180              
1181             =item C<$teng-E<gt>txn_end>
1182              
1183             finish transaction.
1184              
1185             =item C<$teng-E<gt>do($sql, [\%option, @bind_values])>
1186              
1187             Execute the query specified by C<$sql>, using C<%option> and C<@bind_values> as necessary. This pretty much a wrapper around L<http://search.cpan.org/dist/DBI/DBI.pm#do>
1188              
1189             =item C<$teng-E<gt>dbh>
1190              
1191             get database handle.
1192              
1193             =item C<$teng-E<gt>connect(\@connect_info)>
1194              
1195             connect database handle.
1196              
1197             connect_info is [$dsn, $user, $password, $options].
1198              
1199             If you give \@connect_info, create new database connection.
1200              
1201             =item C<$teng-E<gt>disconnect()>
1202              
1203             Disconnects from the currently connected database.
1204              
1205             =item C<$teng-E<gt>suppress_row_objects($flag)>
1206              
1207             set row object creation mode.
1208              
1209             =item C<$teng-E<gt>apply_sql_types($flag)>
1210              
1211             set SQL type application mode.
1212              
1213             see apply_sql_types in L<Teng::Iterator/METHODS>
1214              
1215             =item C<$teng-E<gt>guess_sql_types($flag)>
1216              
1217             set SQL type guessing mode.
1218             this implies apply_sql_types true.
1219              
1220             see guess_sql_types in L<Teng::Iterator/METHODS>
1221              
1222             =item C<$teng-E<gt>set_boolean_value($true, $false)>
1223              
1224             set scalar to correspond boolean.
1225             this is ignored when apply_sql_types is not true.
1226              
1227             $teng->set_boolean_value(JSON::XS::true, JSON::XS::false);
1228              
1229             =item C<$teng-E<gt>load_plugin();>
1230              
1231             $teng->load_plugin($plugin_class, $options);
1232              
1233             This imports plugin class's methods to C<$teng> class
1234             and it calls $plugin_class's init method if it has.
1235              
1236             $plugin_class->init($teng, $options);
1237              
1238             If you want to change imported method name, use C<alias> option.
1239             for example:
1240              
1241             YourDB->load_plugin('BulkInsert', { alias => { bulk_insert => 'isnert_bulk' } });
1242              
1243             BulkInsert's "bulk_insert" method is imported as "insert_bulk".
1244              
1245             =item C<$teng-E<gt>handle_error>
1246              
1247             handling error method.
1248              
1249             =item C<< $teng->connected >>
1250              
1251             check connected or not.
1252              
1253             =item C<< $teng->reconnect >>
1254              
1255             reconnect database
1256              
1257             =item C<< $teng->mode >>
1258              
1259             DEPRECATED AND *WILL* BE REMOVED. PLEASE USE C< no_ping > option.
1260              
1261             =item How do you use display the profiling result?
1262              
1263             use L<Devel::KYTProf>.
1264              
1265             =back
1266              
1267             =head1 TRIGGERS
1268              
1269             Teng does not support triggers (NOTE: do not confuse it with SQL triggers - we're talking about Perl level triggers). If you really want to hook into the various methods, use something like L<Moose>, L<Mouse>, and L<Class::Method::Modifiers>.
1270              
1271             =head1 SEE ALSO
1272              
1273             =head2 Fork
1274              
1275             This module was forked from L<DBIx::Skinny>, around version 0.0732.
1276             many incompatible changes have been made.
1277              
1278             =head1 BUGS AND LIMITATIONS
1279              
1280             No bugs have been reported.
1281              
1282             =head1 AUTHORS
1283              
1284             Atsushi Kobayashi C<< <nekokak __at__ gmail.com> >>
1285              
1286             Tokuhiro Matsuno E<lt>tokuhirom@gmail.comE<gt>
1287              
1288             Daisuke Maki C<< <daisuke@endeworks.jp> >>
1289              
1290             =head1 SUPPORT
1291              
1292             irc: #dbix-skinny@irc.perl.org
1293              
1294             ML: http://groups.google.com/group/dbix-skinny
1295              
1296             =head1 REPOSITORY
1297              
1298             git clone git://github.com/nekokak/p5-teng.git
1299              
1300             =head1 LICENCE AND COPYRIGHT
1301              
1302             Copyright (c) 2010, the Teng L</AUTHOR>. All rights reserved.
1303              
1304             This module is free software; you can redistribute it and/or
1305             modify it under the same terms as Perl itself. See L<perlartistic>.
1306              
1307             =cut
1308