object if needed.
318
|
|
|
|
|
|
|
This will perform a comma (", ") join unless $join_type is specified. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
Tables can be specified with the same arguments as L or another Query can be used as a subquery. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Valid join types are any accepted by the DB. Eg: C<'JOIN'>, C<'LEFT'>, C<'RIGHT'>, C (for comma join), C<'INNER'>, C<'OUTER'>, ... |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
Returns the Table or Query object added. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=cut |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub join_table { |
329
|
18
|
|
|
18
|
1
|
551
|
my($me, $tbl, $type) = @_; |
330
|
18
|
100
|
|
|
|
59
|
if (_isa($tbl, 'DBIx::DBO::Table')) { |
|
|
50
|
|
|
|
|
|
331
|
9
|
100
|
|
|
|
47
|
croak 'This table is already in this query' if defined $me->_table_idx($tbl); |
332
|
8
|
100
|
|
|
|
161
|
croak 'This table is from a different DBO connection' if $me->{DBO} != $tbl->{DBO}; |
333
|
|
|
|
|
|
|
} elsif (_isa($tbl, 'DBIx::DBO::Query')) { |
334
|
|
|
|
|
|
|
# Subquery |
335
|
0
|
0
|
|
|
|
0
|
croak 'This table is from a different DBO connection' if $me->{DBO} != $tbl->{DBO}; |
336
|
|
|
|
|
|
|
} else { |
337
|
9
|
|
|
|
|
36
|
$tbl = $me->_table_class->new($me->{DBO}, $tbl); |
338
|
|
|
|
|
|
|
} |
339
|
16
|
100
|
|
|
|
53
|
if (defined $type) { |
340
|
3
|
|
|
|
|
12
|
$type =~ s/^\s*/ /; |
341
|
3
|
|
|
|
|
17
|
$type =~ s/\s*$/ /; |
342
|
3
|
|
|
|
|
9
|
$type = uc $type; |
343
|
3
|
100
|
|
|
|
18
|
$type .= 'JOIN ' if $type !~ /\bJOIN\b/; |
344
|
|
|
|
|
|
|
} else { |
345
|
13
|
|
|
|
|
27
|
$type = ', '; |
346
|
|
|
|
|
|
|
} |
347
|
16
|
|
|
|
|
25
|
push @{$me->{Tables}}, $tbl; |
|
16
|
|
|
|
|
50
|
|
348
|
16
|
|
|
|
|
31
|
push @{$me->{build_data}{Join}}, $type; |
|
16
|
|
|
|
|
87
|
|
349
|
16
|
|
|
|
|
32
|
push @{$me->{build_data}{Join_On}}, undef; |
|
16
|
|
|
|
|
47
|
|
350
|
16
|
|
|
|
|
23
|
push @{$me->{Join_Bracket_Refs}}, []; |
|
16
|
|
|
|
|
40
|
|
351
|
16
|
|
|
|
|
27
|
push @{$me->{Join_Brackets}}, []; |
|
16
|
|
|
|
|
55
|
|
352
|
16
|
|
|
|
|
43
|
undef $me->{sql}; |
353
|
16
|
|
|
|
|
39
|
undef $me->{build_data}{from}; |
354
|
16
|
|
|
|
|
35
|
undef $me->{build_data}{show}; |
355
|
16
|
|
|
|
|
24
|
undef @{$me->{Columns}}; |
|
16
|
|
|
|
|
31
|
|
356
|
16
|
|
|
|
|
50
|
return $tbl; |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
=head3 C |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
$query->join_on($table_object, $expression1, $operator, $expression2); |
362
|
|
|
|
|
|
|
$query->join_on($table2, $table1 ** 'id', '=', $table2 ** 'id'); |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
Join tables on a specific WHERE clause. The first argument is the table object being joined onto. |
365
|
|
|
|
|
|
|
Then a JOIN ON condition follows, which uses the same arguments as L. |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=cut |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
sub join_on { |
370
|
7
|
|
|
7
|
1
|
589
|
my $me = shift; |
371
|
7
|
|
|
|
|
14
|
my $t2 = shift; |
372
|
7
|
100
|
|
|
|
25
|
my $i = $me->_table_idx($t2) or croak 'Invalid table object to join onto'; |
373
|
|
|
|
|
|
|
|
374
|
6
|
|
|
|
|
53
|
my($col1, $col1_func, $col1_opt) = $me->{DBO}{dbd_class}->_parse_col_val($me, shift); |
375
|
6
|
|
|
|
|
18
|
my $op = shift; |
376
|
6
|
|
|
|
|
29
|
my($col2, $col2_func, $col2_opt) = $me->{DBO}{dbd_class}->_parse_col_val($me, shift); |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# Validate the fields |
379
|
6
|
|
|
|
|
31
|
$me->_validate_where_fields(@$col1, @$col2); |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# Force a new search |
382
|
6
|
|
|
|
|
12
|
undef $me->{sql}; |
383
|
6
|
|
|
|
|
12
|
undef $me->{build_data}{from}; |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
# Find the current Join_On reference |
386
|
6
|
|
100
|
|
|
37
|
my $ref = $me->{build_data}{Join_On}[$i] ||= []; |
387
|
6
|
|
|
|
|
13
|
$ref = $ref->[$_] for (@{$me->{Join_Bracket_Refs}[$i]}); |
|
6
|
|
|
|
|
22
|
|
388
|
|
|
|
|
|
|
|
389
|
6
|
100
|
|
|
|
29
|
$me->{build_data}{Join}[$i] = ' JOIN ' if $me->{build_data}{Join}[$i] eq ', '; |
390
|
6
|
|
|
|
|
30
|
$me->_add_where($ref, $op, $col1, $col1_func, $col1_opt, $col2, $col2_func, $col2_opt, @_); |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=head3 C, C |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
$query->open_join_on_bracket($table, 'OR'); |
396
|
|
|
|
|
|
|
$query->join_on(... |
397
|
|
|
|
|
|
|
$query->close_join_on_bracket($table); |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
Equivalent to L, but for the JOIN ON clause. |
400
|
|
|
|
|
|
|
The first argument is the table being joined onto. |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=cut |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
sub open_join_on_bracket { |
405
|
3
|
|
|
3
|
1
|
1048
|
my $me = shift; |
406
|
3
|
100
|
|
|
|
14
|
my $tbl = shift or croak 'Invalid table object for join on clause'; |
407
|
2
|
100
|
|
|
|
5
|
my $i = $me->_table_idx($tbl) or croak 'No such table object in the join'; |
408
|
1
|
|
50
|
|
|
8
|
$me->_open_bracket($me->{Join_Brackets}[$i], $me->{Join_Bracket_Refs}[$i], $me->{build_data}{Join_On}[$i] ||= [], @_); |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sub close_join_on_bracket { |
412
|
3
|
|
|
3
|
1
|
1042
|
my $me = shift; |
413
|
3
|
100
|
|
|
|
14
|
my $tbl = shift or croak 'Invalid table object for join on clause'; |
414
|
2
|
100
|
|
|
|
8
|
my $i = $me->_table_idx($tbl) or croak 'No such table object in the join'; |
415
|
1
|
|
|
|
|
7
|
$me->_close_bracket($me->{Join_Brackets}[$i], $me->{Join_Bracket_Refs}[$i]); |
416
|
|
|
|
|
|
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=head3 C |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
Restrict the query with the condition specified (WHERE clause). |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
$query->where($expression1, $operator, $expression2); |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
C<$operator> is one of: C<'=', '', '<', 'E', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE', 'BETWEEN', 'NOT BETWEEN', ...> |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
C<$expression>s can be any of the following: |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=over 4 |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=item * |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
A scalar value: C<123> or C<'hello'> (or for C<$expression1> a column name: C<'id'>) |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
$query->where('name', '<>', 'John'); |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=item * |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
A scalar reference: C<\"22 * 3"> (These are passed unquoted in the SQL statement!) |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
$query->where(\'CONCAT(id, name)', '=', \'"22John"'); |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
=item * |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
An array reference: C<[1, 3, 5]> (Used with C and C etc) |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
$query->where('id', 'NOT IN', [21, 22, 25, 39]); |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
=item * |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
A Column object: C<$table ** 'id'> or C<$table-Ecolumn('id')> |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
$query->where($table1 ** 'id', '=', $table2 ** 'id'); |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=item * |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
A Query object, to be used as a subquery. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
$query->where('id', '>', $subquery); |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
=item * |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
A hash reference: see L |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
=back |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
Multiple C expressions are combined I using the preferred aggregator C<'AND'> (unless L was used to change this). So that when you add where expressions to the query, they will be Ced together. However some expressions that refer to the same column will automatically be Ced instead where this makes sense, currently: C<'='>, C<'IS NULL'>, C<'E=E'>, C<'IN'> and C<'BETWEEN'>. Similarly, when the preferred aggregator is C<'OR'> the following operators will be Ced together: C<'!='>, C<'IS NOT NULL'>, C<'EE'>, C<'NOT IN'> and C<'NOT BETWEEN'>. |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
$query->where('id', '=', 5); |
469
|
|
|
|
|
|
|
$query->where('name', '=', 'Bob'); |
470
|
|
|
|
|
|
|
$query->where('id', '=', 7); |
471
|
|
|
|
|
|
|
$query->where(... |
472
|
|
|
|
|
|
|
# Produces: WHERE ("id" = 5 OR "id" = 7) AND "name" = 'Bob' AND ... |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=cut |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
sub where { |
477
|
20
|
|
|
20
|
1
|
2285
|
my $me = shift; |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
# If the $fld is just a scalar use it as a column name not a value |
480
|
20
|
|
|
|
|
116
|
my($fld, $fld_func, $fld_opt) = $me->{DBO}{dbd_class}->_parse_col_val($me, shift); |
481
|
20
|
|
|
|
|
74
|
my $op = shift; |
482
|
20
|
|
|
|
|
111
|
my($val, $val_func, $val_opt) = $me->{DBO}{dbd_class}->_parse_val($me, shift, Check => 'Auto'); |
483
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
# Validate the fields |
485
|
19
|
|
|
|
|
65
|
$me->_validate_where_fields(@$fld, @$val); |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# Force a new search |
488
|
19
|
|
|
|
|
35
|
undef $me->{sql}; |
489
|
19
|
|
|
|
|
30
|
undef $me->{build_data}{where}; |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
# Find the current Where_Data reference |
492
|
19
|
|
100
|
|
|
108
|
my $ref = $me->{build_data}{Where_Data} ||= []; |
493
|
19
|
|
|
|
|
26
|
$ref = $ref->[$_] for (@{$me->{Where_Bracket_Refs}}); |
|
19
|
|
|
|
|
60
|
|
494
|
|
|
|
|
|
|
|
495
|
19
|
|
|
|
|
67
|
$me->_add_where($ref, $op, $fld, $fld_func, $fld_opt, $val, $val_func, $val_opt, @_); |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=head3 C |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
$query->unwhere(); |
501
|
|
|
|
|
|
|
$query->unwhere($column); |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
Removes all previously added L restrictions for a column. |
504
|
|
|
|
|
|
|
If no column is provided, the I WHERE clause is removed. |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=cut |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
sub unwhere { |
509
|
16
|
|
|
16
|
1
|
29
|
my $me = shift; |
510
|
16
|
|
|
|
|
91
|
$me->_del_where('Where', @_); |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
sub _validate_where_fields { |
514
|
28
|
|
|
28
|
|
50
|
my $me = shift; |
515
|
28
|
|
|
|
|
49
|
for my $f (@_) { |
516
|
58
|
100
|
|
|
|
134
|
if (_isa($f, 'DBIx::DBO::Column')) { |
|
|
100
|
|
|
|
|
|
517
|
32
|
|
|
|
|
125
|
$me->{DBO}{dbd_class}->_valid_col($me, $f); |
518
|
|
|
|
|
|
|
} elsif (my $type = ref $f) { |
519
|
1
|
50
|
33
|
|
|
7
|
croak 'Invalid value type: '.$type if $type ne 'SCALAR' and not _isa($f, 'DBIx::DBO::Query'); |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
sub _del_where { |
525
|
32
|
|
|
32
|
|
52
|
my $me = shift; |
526
|
32
|
|
|
|
|
51
|
my $clause = shift; |
527
|
|
|
|
|
|
|
|
528
|
32
|
100
|
|
|
|
76
|
if (@_) { |
529
|
4
|
|
|
|
|
1346
|
require Data::Dumper; |
530
|
4
|
|
|
|
|
6648
|
my($fld, $fld_func, $fld_opt) = $me->{DBO}{dbd_class}->_parse_col_val($me, shift); |
531
|
|
|
|
|
|
|
# TODO: Validate the fields? |
532
|
|
|
|
|
|
|
|
533
|
4
|
50
|
|
|
|
21
|
return unless exists $me->{build_data}{$clause.'_Data'}; |
534
|
|
|
|
|
|
|
# Find the current Where_Data reference |
535
|
4
|
|
|
|
|
11
|
my $ref = $me->{build_data}{$clause.'_Data'}; |
536
|
4
|
|
|
|
|
9
|
$ref = $ref->[$_] for (@{$me->{$clause.'_Bracket_Refs'}}); |
|
4
|
|
|
|
|
19
|
|
537
|
|
|
|
|
|
|
|
538
|
4
|
|
|
|
|
11
|
local $Data::Dumper::Indent = 0; |
539
|
4
|
|
|
|
|
7
|
local $Data::Dumper::Maxdepth = 2; |
540
|
11
|
|
|
|
|
719
|
my @match = grep { |
541
|
4
|
|
|
|
|
15
|
Data::Dumper::Dumper($fld, $fld_func, $fld_opt) eq Data::Dumper::Dumper(@{$ref->[$_]}[1,2,3]) |
|
11
|
|
|
|
|
437
|
|
542
|
|
|
|
|
|
|
} 0 .. $#$ref; |
543
|
|
|
|
|
|
|
|
544
|
4
|
100
|
|
|
|
454
|
if (@_) { |
545
|
1
|
|
|
|
|
3
|
my $op = shift; |
546
|
1
|
|
|
|
|
8
|
my($val, $val_func, $val_opt) = $me->{DBO}{dbd_class}->_parse_val($me, shift, Check => 'Auto'); |
547
|
|
|
|
|
|
|
|
548
|
3
|
|
|
|
|
144
|
@match = grep { |
549
|
1
|
|
|
|
|
4
|
Data::Dumper::Dumper($op, $val, $val_func, $val_opt) eq Data::Dumper::Dumper(@{$ref->[$_]}[0,4,5,6]) |
|
3
|
|
|
|
|
100
|
|
550
|
|
|
|
|
|
|
} @match; |
551
|
|
|
|
|
|
|
} |
552
|
4
|
|
|
|
|
73
|
splice @$ref, $_, 1 for reverse @match; |
553
|
|
|
|
|
|
|
} else { |
554
|
28
|
|
|
|
|
128
|
delete $me->{build_data}{$clause.'_Data'}; |
555
|
28
|
|
|
|
|
74
|
$me->{$clause.'_Bracket_Refs'} = []; |
556
|
28
|
|
|
|
|
82
|
$me->{$clause.'_Brackets'} = []; |
557
|
|
|
|
|
|
|
} |
558
|
|
|
|
|
|
|
# This forces a new search |
559
|
32
|
|
|
|
|
62
|
undef $me->{sql}; |
560
|
32
|
|
|
|
|
150
|
undef $me->{build_data}{lc $clause}; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
## |
564
|
|
|
|
|
|
|
# This will add an arrayref to the $ref given. |
565
|
|
|
|
|
|
|
# The arrayref will contain 8 values: |
566
|
|
|
|
|
|
|
# $op, $fld, $fld_func, $fld_opt, $val, $val_func, $val_opt, $force |
567
|
|
|
|
|
|
|
# $op is the operator (those supported differ by DBD) |
568
|
|
|
|
|
|
|
# $fld_func is undef or a scalar of the form '? AND ?' or 'POSITION(? IN ?)' |
569
|
|
|
|
|
|
|
# $fld is an arrayref of columns/values for use with $fld_func |
570
|
|
|
|
|
|
|
# $val_func is similar to $fld_func |
571
|
|
|
|
|
|
|
# $val is an arrayref of values for use with $val_func |
572
|
|
|
|
|
|
|
# $force is one of undef / 'AND' / 'OR' which if defined, overrides the default aggregator |
573
|
|
|
|
|
|
|
## |
574
|
|
|
|
|
|
|
sub _add_where { |
575
|
28
|
|
|
28
|
|
41
|
my $me = shift; |
576
|
28
|
|
|
|
|
66
|
my($ref, $op, $fld, $fld_func, $fld_opt, $val, $val_func, $val_opt, %opt) = @_; |
577
|
|
|
|
|
|
|
|
578
|
28
|
50
|
66
|
|
|
98
|
croak 'Invalid option, FORCE must be AND or OR' |
|
|
|
66
|
|
|
|
|
579
|
|
|
|
|
|
|
if defined $opt{FORCE} and $opt{FORCE} ne 'AND' and $opt{FORCE} ne 'OR'; |
580
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
# Deal with NULL values |
582
|
28
|
100
|
|
|
|
79
|
$op = '<>' if $op eq '!='; # Use the valid SQL op |
583
|
28
|
100
|
100
|
|
|
193
|
if (@$val == 1 and !defined $val->[0] and !defined $val_func) { |
|
|
|
66
|
|
|
|
|
584
|
2
|
100
|
|
|
|
9
|
if ($op eq '=') { $op = 'IS'; $val_func = 'NULL'; delete $val->[0]; } |
|
1
|
50
|
|
|
|
2
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
585
|
1
|
|
|
|
|
2
|
elsif ($op eq '<>') { $op = 'IS NOT'; $val_func = 'NULL'; delete $val->[0]; } |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
3
|
|
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
# Deal with array values: BETWEEN & IN |
589
|
28
|
100
|
|
|
|
79
|
unless (defined $val_func) { |
590
|
19
|
100
|
100
|
|
|
165
|
if ($op eq 'BETWEEN' or $op eq 'NOT BETWEEN') { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
591
|
3
|
100
|
66
|
|
|
23
|
croak 'Invalid value argument, BETWEEN requires 2 values' |
592
|
|
|
|
|
|
|
if ref $val ne 'ARRAY' or @$val != 2; |
593
|
2
|
|
|
|
|
16
|
$val_func = $me->{DBO}{dbd_class}->PLACEHOLDER.' AND '.$me->{DBO}{dbd_class}->PLACEHOLDER; |
594
|
|
|
|
|
|
|
} elsif ($op eq 'IN' or $op eq 'NOT IN') { |
595
|
3
|
50
|
|
|
|
8
|
if (ref $val eq 'ARRAY') { |
596
|
3
|
50
|
|
|
|
10
|
croak 'Invalid value argument, IN requires at least 1 value' if @$val == 0; |
597
|
|
|
|
|
|
|
} else { |
598
|
0
|
|
|
|
|
0
|
$val = [ $val ]; |
599
|
|
|
|
|
|
|
} |
600
|
|
|
|
|
|
|
# Add to previous 'IN' and 'NOT IN' Where expressions |
601
|
3
|
|
|
|
|
20
|
my $op_ag = $me->{DBO}{dbd_class}->_op_ag($op); |
602
|
3
|
50
|
33
|
|
|
10
|
unless ($opt{FORCE} and $opt{FORCE} ne $op_ag) { |
603
|
3
|
|
|
|
|
27
|
for my $lim (grep $$_[0] eq $op, @$ref) { |
604
|
|
|
|
|
|
|
# $fld and $$lim[1] are always ARRAY refs |
605
|
1
|
50
|
|
|
|
3
|
next if "@{$$lim[1]}" ne "@$fld"; |
|
1
|
|
|
|
|
11
|
|
606
|
1
|
50
|
33
|
|
|
10
|
last if $$lim[7] and $$lim[7] ne $op_ag; |
607
|
1
|
50
|
|
|
|
6
|
last if $$lim[5] ne '('.join(',', ($me->{DBO}{dbd_class}->PLACEHOLDER) x @{$$lim[4]}).')'; |
|
1
|
|
|
|
|
11
|
|
608
|
1
|
|
|
|
|
3
|
push @{$$lim[4]}, @$val; |
|
1
|
|
|
|
|
5
|
|
609
|
1
|
|
|
|
|
6
|
$$lim[5] = '('.join(',', ($me->{DBO}{dbd_class}->PLACEHOLDER) x @{$$lim[4]}).')'; |
|
1
|
|
|
|
|
5
|
|
610
|
1
|
|
|
|
|
7
|
return; |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
} |
613
|
2
|
|
|
|
|
24
|
$val_func = '('.join(',', ($me->{DBO}{dbd_class}->PLACEHOLDER) x @$val).')'; |
614
|
|
|
|
|
|
|
} elsif (@$val != 1) { |
615
|
|
|
|
|
|
|
# Check that there is only 1 placeholder |
616
|
1
|
|
|
|
|
5
|
croak 'Wrong number of fields/values, called with '.@$val.' while needing 1'; |
617
|
|
|
|
|
|
|
} |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
25
|
|
|
|
|
39
|
push @{$ref}, [ $op, $fld, $fld_func, $fld_opt, $val, $val_func, $val_opt, $opt{FORCE} ]; |
|
25
|
|
|
|
|
148
|
|
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
=head3 C, C |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
$query->open_bracket('OR'); |
626
|
|
|
|
|
|
|
$query->where( ... |
627
|
|
|
|
|
|
|
$query->where( ... |
628
|
|
|
|
|
|
|
$query->close_bracket; |
629
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
Used to group C expressions together in parenthesis using either C<'AND'> or C<'OR'> as the preferred aggregator. |
631
|
|
|
|
|
|
|
All the C calls made between C and C will be inside the parenthesis. |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
Without any parenthesis C<'AND'> is the preferred aggregator. |
634
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
=cut |
636
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
sub open_bracket { |
638
|
2
|
|
|
2
|
1
|
3
|
my $me = shift; |
639
|
2
|
|
50
|
|
|
14
|
$me->_open_bracket($me->{Where_Brackets}, $me->{Where_Bracket_Refs}, $me->{build_data}{Where_Data} ||= [], @_); |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
sub _open_bracket { |
643
|
3
|
|
|
3
|
|
8
|
my($me, $brackets, $bracket_refs, $ref, $ag) = @_; |
644
|
3
|
50
|
33
|
|
|
34
|
croak 'Invalid argument MUST be AND or OR' if !$ag or $ag !~ /^(AND|OR)$/; |
645
|
3
|
100
|
|
|
|
8
|
my $last = @$brackets ? $brackets->[-1] : 'AND'; |
646
|
3
|
50
|
|
|
|
15
|
if ($ag ne $last) { |
647
|
|
|
|
|
|
|
# Find the current data reference |
648
|
3
|
|
|
|
|
9
|
$ref = $ref->[$_] for @$bracket_refs; |
649
|
|
|
|
|
|
|
|
650
|
3
|
|
|
|
|
8
|
push @$ref, []; |
651
|
3
|
|
|
|
|
4
|
push @$bracket_refs, $#$ref; |
652
|
|
|
|
|
|
|
} |
653
|
3
|
|
|
|
|
15
|
push @$brackets, $ag; |
654
|
|
|
|
|
|
|
} |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
sub close_bracket { |
657
|
2
|
|
|
2
|
1
|
5
|
my $me = shift; |
658
|
2
|
|
|
|
|
10
|
$me->_close_bracket($me->{Where_Brackets}, $me->{Where_Bracket_Refs}); |
659
|
|
|
|
|
|
|
} |
660
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
sub _close_bracket { |
662
|
3
|
|
|
3
|
|
8
|
my($me, $brackets, $bracket_refs) = @_; |
663
|
3
|
50
|
|
|
|
5
|
my $ag = pop @{$brackets} or croak "Can't close bracket with no open bracket!"; |
|
3
|
|
|
|
|
15
|
|
664
|
3
|
100
|
|
|
|
14
|
my $last = @$brackets ? $brackets->[-1] : 'AND'; |
665
|
3
|
50
|
|
|
|
13
|
pop @$bracket_refs if $last ne $ag; |
666
|
3
|
|
|
|
|
13
|
return $ag; |
667
|
|
|
|
|
|
|
} |
668
|
|
|
|
|
|
|
|
669
|
|
|
|
|
|
|
=head3 C |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
$query->group_by('column', ...); |
672
|
|
|
|
|
|
|
$query->group_by($table ** 'column', ...); |
673
|
|
|
|
|
|
|
$query->group_by({ COL => $table ** 'column', ORDER => 'DESC' }, ...); |
674
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
Group the results by the column(s) listed. This will replace the GROUP BY clause. |
676
|
|
|
|
|
|
|
To remove the GROUP BY clause simply call C without any columns. |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
=cut |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
sub group_by { |
681
|
17
|
|
|
17
|
1
|
31
|
my $me = shift; |
682
|
17
|
|
|
|
|
34
|
undef $me->{sql}; |
683
|
17
|
|
|
|
|
53
|
undef $me->{build_data}{group}; |
684
|
17
|
|
|
|
|
26
|
undef @{$me->{build_data}{GroupBy}}; |
|
17
|
|
|
|
|
96
|
|
685
|
17
|
|
|
|
|
47
|
for my $col (@_) { |
686
|
3
|
|
|
|
|
14
|
my @group = $me->{DBO}{dbd_class}->_parse_col_val($me, $col); |
687
|
3
|
|
|
|
|
8
|
push @{$me->{build_data}{GroupBy}}, \@group; |
|
3
|
|
|
|
|
17
|
|
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
=head3 C |
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
Restrict the query with the condition specified (HAVING clause). This takes the same arguments as L. |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
$query->having($expression1, $operator, $expression2); |
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=cut |
698
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
sub having { |
700
|
3
|
|
|
3
|
1
|
4
|
my $me = shift; |
701
|
|
|
|
|
|
|
|
702
|
|
|
|
|
|
|
# If the $fld is just a scalar use it as a column name not a value |
703
|
3
|
|
|
|
|
13
|
my($fld, $fld_func, $fld_opt) = $me->{DBO}{dbd_class}->_parse_col_val($me, shift); |
704
|
3
|
|
|
|
|
7
|
my $op = shift; |
705
|
3
|
|
|
|
|
13
|
my($val, $val_func, $val_opt) = $me->{DBO}{dbd_class}->_parse_val($me, shift, Check => 'Auto'); |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
# Validate the fields |
708
|
3
|
|
|
|
|
10
|
$me->_validate_where_fields(@$fld, @$val); |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
# Force a new search |
711
|
3
|
|
|
|
|
5
|
undef $me->{sql}; |
712
|
3
|
|
|
|
|
6
|
undef $me->{build_data}{having}; |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
# Find the current Having_Data reference |
715
|
3
|
|
100
|
|
|
12
|
my $ref = $me->{build_data}{Having_Data} ||= []; |
716
|
3
|
|
|
|
|
5
|
$ref = $ref->[$_] for (@{$me->{Having_Bracket_Refs}}); |
|
3
|
|
|
|
|
8
|
|
717
|
|
|
|
|
|
|
|
718
|
3
|
|
|
|
|
10
|
$me->_add_where($ref, $op, $fld, $fld_func, $fld_opt, $val, $val_func, $val_opt, @_); |
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
=head3 C |
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
$query->unhaving(); |
724
|
|
|
|
|
|
|
$query->unhaving($column); |
725
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
Removes all previously added L restrictions for a column. |
727
|
|
|
|
|
|
|
If no column is provided, the I HAVING clause is removed. |
728
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
=cut |
730
|
|
|
|
|
|
|
|
731
|
|
|
|
|
|
|
sub unhaving { |
732
|
16
|
|
|
16
|
1
|
33
|
my $me = shift; |
733
|
16
|
|
|
|
|
53
|
$me->_del_where('Having', @_); |
734
|
|
|
|
|
|
|
} |
735
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
=head3 C |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
$query->order_by('column', ...); |
739
|
|
|
|
|
|
|
$query->order_by($table ** 'column', ...); |
740
|
|
|
|
|
|
|
$query->order_by({ COL => $table ** 'column', ORDER => 'DESC' }, ...); |
741
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
Order the results by the column(s) listed. This will replace the ORDER BY clause. |
743
|
|
|
|
|
|
|
To remove the ORDER BY clause simply call C without any columns. |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
=cut |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
sub order_by { |
748
|
24
|
|
|
24
|
1
|
55
|
my $me = shift; |
749
|
24
|
|
|
|
|
44
|
undef $me->{sql}; |
750
|
24
|
|
|
|
|
55
|
undef $me->{build_data}{order}; |
751
|
24
|
|
|
|
|
37
|
undef @{$me->{build_data}{OrderBy}}; |
|
24
|
|
|
|
|
77
|
|
752
|
24
|
|
|
|
|
59
|
for my $col (@_) { |
753
|
9
|
|
|
|
|
51
|
my @order = $me->{DBO}{dbd_class}->_parse_col_val($me, $col); |
754
|
9
|
|
|
|
|
23
|
push @{$me->{build_data}{OrderBy}}, \@order; |
|
9
|
|
|
|
|
45
|
|
755
|
|
|
|
|
|
|
} |
756
|
|
|
|
|
|
|
} |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
=head3 C |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
$query->limit; |
761
|
|
|
|
|
|
|
$query->limit($rows); |
762
|
|
|
|
|
|
|
$query->limit($rows, $offset); |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
Limit the maximum number of rows returned to C<$rows>, optionally skipping the first C<$offset> rows. |
765
|
|
|
|
|
|
|
When called without arguments or if C<$rows> is undefined, the limit is removed. |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
NB. Oracle does not support pagging prior to version 12c, so this has been implemented in software, |
768
|
|
|
|
|
|
|
, but if an offset is given, an extra column "_DBO_ROWNUM_" is added to the Query to achieve this. |
769
|
|
|
|
|
|
|
TODO: Implement the new "FIRST n / NEXT n" clause if connected to a 12c database. |
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
=cut |
772
|
|
|
|
|
|
|
|
773
|
|
|
|
|
|
|
sub limit { |
774
|
18
|
|
|
18
|
1
|
37
|
my($me, $rows, $offset) = @_; |
775
|
18
|
|
|
|
|
32
|
undef $me->{sql}; |
776
|
18
|
|
|
|
|
43
|
undef $me->{build_data}{limit}; |
777
|
18
|
100
|
|
|
|
114
|
return undef $me->{build_data}{LimitOffset} unless defined $rows; |
778
|
4
|
|
33
|
|
|
37
|
/^\d+$/ or croak "Invalid argument '$_' in limit" for grep defined, $rows, $offset; |
779
|
4
|
|
|
|
|
7
|
@{$me->{build_data}{LimitOffset}} = ($rows, $offset); |
|
4
|
|
|
|
|
15
|
|
780
|
|
|
|
|
|
|
} |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
=head3 C |
783
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
$query->arrayref; |
785
|
|
|
|
|
|
|
$query->arrayref(\%attr); |
786
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
Run the query using Lselectall_arrayref|DBI/"selectall_arrayref"> which returns the result as an arrayref. |
788
|
|
|
|
|
|
|
You can specify a slice by including a 'Slice' or 'Columns' attribute in C<%attr> - See Lselectall_arrayref|DBI/"selectall_arrayref">. |
789
|
|
|
|
|
|
|
|
790
|
|
|
|
|
|
|
=cut |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
sub arrayref { |
793
|
3
|
|
|
3
|
1
|
6
|
my($me, $attr) = @_; |
794
|
3
|
|
|
|
|
15
|
$me->{DBO}{dbd_class}->_selectall_arrayref($me, $me->sql, $attr, |
795
|
|
|
|
|
|
|
$me->{DBO}{dbd_class}->_bind_params_select($me)); |
796
|
|
|
|
|
|
|
} |
797
|
|
|
|
|
|
|
|
798
|
|
|
|
|
|
|
=head3 C |
799
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
$query->hashref($key_field); |
801
|
|
|
|
|
|
|
$query->hashref($key_field, \%attr); |
802
|
|
|
|
|
|
|
|
803
|
|
|
|
|
|
|
Run the query using Lselectall_hashref|DBI/"selectall_hashref"> which returns the result as an hashref. |
804
|
|
|
|
|
|
|
C<$key_field> defines which column, or columns, are used as keys in the returned hash. |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
=cut |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
sub hashref { |
809
|
1
|
|
|
1
|
1
|
4
|
my($me, $key, $attr) = @_; |
810
|
1
|
|
|
|
|
5
|
$me->{DBO}{dbd_class}->_selectall_hashref($me, $me->sql, $key, $attr, |
811
|
|
|
|
|
|
|
$me->{DBO}{dbd_class}->_bind_params_select($me)); |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
=head3 C |
815
|
|
|
|
|
|
|
|
816
|
|
|
|
|
|
|
$query->col_arrayref; |
817
|
|
|
|
|
|
|
$query->col_arrayref(\%attr); |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
Run the query using Lselectcol_arrayref|DBI/"selectcol_arrayref"> which returns the result as an arrayref of the values of each row in one array. By default it pushes all the columns requested by the L method onto the result array (this differs from the C). Or to specify which columns to include in the result use the 'Columns' attribute in C<%attr> - see Lselectcol_arrayref|DBI/"selectcol_arrayref">. |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
=cut |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
sub col_arrayref { |
824
|
3
|
|
|
3
|
1
|
11
|
my($me, $attr) = @_; |
825
|
3
|
|
|
|
|
12
|
my($sql, @bind) = ($me->sql, $me->{DBO}{dbd_class}->_bind_params_select($me)); |
826
|
3
|
|
|
|
|
23
|
$me->{DBO}{dbd_class}->_sql($me, $sql, @bind); |
827
|
3
|
50
|
|
|
|
9
|
my $sth = $me->rdbh->prepare($sql, $attr) or return; |
828
|
3
|
100
|
|
|
|
541
|
unless (defined $attr->{Columns}) { |
829
|
|
|
|
|
|
|
# Some drivers don't provide $sth->{NUM_OF_FIELDS} until after execute is called |
830
|
1
|
50
|
|
|
|
14
|
if ($sth->{NUM_OF_FIELDS}) { |
831
|
1
|
|
|
|
|
8
|
$attr->{Columns} = [1 .. $sth->{NUM_OF_FIELDS}]; |
832
|
|
|
|
|
|
|
} else { |
833
|
0
|
0
|
|
|
|
0
|
$sth->execute(@bind) or return; |
834
|
0
|
|
|
|
|
0
|
my @col; |
835
|
0
|
0
|
|
|
|
0
|
if (my $max = $attr->{MaxRows}) { |
836
|
0
|
|
0
|
|
|
0
|
push @col, @$_ while 0 < $max-- and $_ = $sth->fetch; |
837
|
|
|
|
|
|
|
} else { |
838
|
0
|
|
|
|
|
0
|
push @col, @$_ while $_ = $sth->fetch; |
839
|
|
|
|
|
|
|
} |
840
|
0
|
|
|
|
|
0
|
return \@col; |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
} |
843
|
3
|
|
|
|
|
12
|
return $me->rdbh->selectcol_arrayref($sth, $attr, @bind); |
844
|
|
|
|
|
|
|
} |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
=head3 C |
847
|
|
|
|
|
|
|
|
848
|
|
|
|
|
|
|
my $row = $query->fetch; |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
Fetch the next row from the query. This will run/rerun the query if needed. |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
Returns a L object or undefined if there are no more rows. |
853
|
|
|
|
|
|
|
|
854
|
|
|
|
|
|
|
=cut |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
sub fetch { |
857
|
30
|
|
|
30
|
1
|
27824
|
my $me = $_[0]; |
858
|
|
|
|
|
|
|
# Prepare and/or execute the query if needed |
859
|
30
|
50
|
66
|
|
|
90
|
$me->_sth and ($me->{Active} or $me->run) |
|
|
|
33
|
|
|
|
|
860
|
|
|
|
|
|
|
or croak $me->rdbh->errstr; |
861
|
|
|
|
|
|
|
# Detach the old row if there is still another reference to it |
862
|
30
|
50
|
66
|
|
|
290
|
if (defined $me->{Row} and SvREFCNT(${$me->{Row}}) > 1) { |
|
23
|
|
|
|
|
403
|
|
863
|
0
|
|
|
|
|
0
|
$me->{Row}->_detach; |
864
|
|
|
|
|
|
|
} |
865
|
|
|
|
|
|
|
|
866
|
30
|
|
|
|
|
95
|
my $row = $me->row; |
867
|
30
|
50
|
|
|
|
84
|
if (exists $me->{cache}) { |
868
|
30
|
100
|
|
|
|
56
|
if ($me->{cache}{idx} < @{$me->{cache}{data}}) { |
|
30
|
|
|
|
|
103
|
|
869
|
26
|
|
|
|
|
36
|
@{$me->{cache}{array}}[0..$#{$me->{cache}{array}}] = @{$me->{cache}{data}[$me->{cache}{idx}++]}; |
|
26
|
|
|
|
|
76
|
|
|
26
|
|
|
|
|
57
|
|
|
26
|
|
|
|
|
96
|
|
870
|
26
|
|
|
|
|
77
|
$$row->{array} = $me->{cache}{array}; |
871
|
26
|
|
|
|
|
54
|
$$row->{hash} = $me->{hash}; |
872
|
26
|
|
|
|
|
154
|
return $row; |
873
|
|
|
|
|
|
|
} |
874
|
4
|
|
|
|
|
13
|
undef $$row->{array}; |
875
|
4
|
|
|
|
|
12
|
$me->{cache}{idx} = 0; |
876
|
|
|
|
|
|
|
} else { |
877
|
|
|
|
|
|
|
# Fetch and store the data then return the Row on success and undef on failure or no more rows |
878
|
0
|
0
|
|
|
|
0
|
if ($$row->{array} = $me->{sth}->fetch) { |
879
|
0
|
|
|
|
|
0
|
$$row->{hash} = $me->{hash}; |
880
|
0
|
|
|
|
|
0
|
return $row; |
881
|
|
|
|
|
|
|
} |
882
|
0
|
|
|
|
|
0
|
$me->{Active} = 0; |
883
|
|
|
|
|
|
|
} |
884
|
4
|
|
|
|
|
11
|
$$row->{hash} = {}; |
885
|
4
|
|
|
|
|
25
|
return; |
886
|
|
|
|
|
|
|
} |
887
|
|
|
|
|
|
|
|
888
|
|
|
|
|
|
|
=head3 C |
889
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
my $row = $query->row; |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
Returns the L object for the current row from the query or an empty L object if there is no current row. |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
=cut |
895
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
sub row { |
897
|
37
|
|
|
37
|
1
|
76
|
my $me = $_[0]; |
898
|
37
|
|
|
|
|
121
|
$me->sql; # Build the SQL and detach the Row if needed |
899
|
37
|
|
66
|
|
|
223
|
$me->{Row} ||= $me->_row_class->new($me->{DBO}, $me); |
900
|
|
|
|
|
|
|
} |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
=head3 C |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
$query->run; |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
Run/rerun the query. |
907
|
|
|
|
|
|
|
This is called automatically before fetching the first row. |
908
|
|
|
|
|
|
|
|
909
|
|
|
|
|
|
|
=cut |
910
|
|
|
|
|
|
|
|
911
|
|
|
|
|
|
|
sub run { |
912
|
15
|
|
|
15
|
1
|
7472
|
my $me = shift; |
913
|
15
|
|
|
|
|
51
|
$me->sql; # Build the SQL and detach the Row if needed |
914
|
15
|
100
|
|
|
|
47
|
if (defined $me->{Row}) { |
915
|
11
|
|
|
|
|
21
|
undef ${$me->{Row}}->{array}; |
|
11
|
|
|
|
|
79
|
|
916
|
11
|
|
|
|
|
25
|
${$me->{Row}}->{hash} = {}; |
|
11
|
|
|
|
|
33
|
|
917
|
|
|
|
|
|
|
} |
918
|
|
|
|
|
|
|
|
919
|
15
|
50
|
|
|
|
66
|
my $rv = $me->_execute or return undef; |
920
|
15
|
|
|
|
|
53
|
$me->{Active} = 1; |
921
|
15
|
|
|
|
|
54
|
$me->_bind_cols_to_hash; |
922
|
15
|
50
|
|
|
|
38
|
if ($me->config('CacheQuery')) { |
923
|
15
|
|
|
|
|
333
|
$me->{cache}{data} = $me->{sth}->fetchall_arrayref; |
924
|
15
|
|
|
|
|
100
|
$me->{cache}{idx} = 0; |
925
|
|
|
|
|
|
|
} else { |
926
|
0
|
|
|
|
|
0
|
delete $me->{cache}; |
927
|
|
|
|
|
|
|
} |
928
|
15
|
|
|
|
|
87
|
return $rv; |
929
|
|
|
|
|
|
|
} |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
sub _execute { |
932
|
15
|
|
|
15
|
|
28
|
my $me = shift; |
933
|
15
|
|
|
|
|
92
|
$me->{DBO}{dbd_class}->_sql($me, $me->sql, $me->{DBO}{dbd_class}->_bind_params_select($me)); |
934
|
15
|
50
|
|
|
|
47
|
$me->_sth or return; |
935
|
15
|
|
|
|
|
800
|
$me->{sth}->execute($me->{DBO}{dbd_class}->_bind_params_select($me)); |
936
|
|
|
|
|
|
|
} |
937
|
|
|
|
|
|
|
|
938
|
|
|
|
|
|
|
sub _bind_cols_to_hash { |
939
|
15
|
|
|
15
|
|
29
|
my $me = shift; |
940
|
15
|
100
|
|
|
|
54
|
unless ($me->{hash}) { |
941
|
|
|
|
|
|
|
# Bind only to the first column of the same name |
942
|
14
|
|
|
|
|
18
|
@{$me->{Columns}} = @{$me->{sth}{NAME}}; |
|
14
|
|
|
|
|
58
|
|
|
14
|
|
|
|
|
206
|
|
943
|
14
|
50
|
|
|
|
62
|
if ($me->config('CacheQuery')) { |
944
|
14
|
|
|
|
|
32
|
@{$me->{cache}{array}} = (undef) x @{$me->{Columns}}; |
|
14
|
|
|
|
|
59
|
|
|
14
|
|
|
|
|
44
|
|
945
|
14
|
|
|
|
|
33
|
$me->{hash} = \my %hash; |
946
|
14
|
|
|
|
|
21
|
my $i = 0; |
947
|
14
|
|
|
|
|
32
|
for (@{$me->{Columns}}) { |
|
14
|
|
|
|
|
38
|
|
948
|
36
|
100
|
|
|
|
166
|
_hv_store(%hash, $_, $me->{cache}{array}[$i]) unless exists $hash{$_}; |
949
|
36
|
|
|
|
|
68
|
$i++; |
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
} else { |
952
|
0
|
|
|
|
|
0
|
my $i; |
953
|
0
|
|
|
|
|
0
|
for (@{$me->{Columns}}) { |
|
0
|
|
|
|
|
0
|
|
954
|
0
|
|
|
|
|
0
|
$i++; |
955
|
0
|
0
|
|
|
|
0
|
$me->{sth}->bind_col($i, \$me->{hash}{$_}) unless exists $me->{hash}{$_}; |
956
|
|
|
|
|
|
|
} |
957
|
|
|
|
|
|
|
} |
958
|
|
|
|
|
|
|
} |
959
|
|
|
|
|
|
|
} |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
=head3 C |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
my $row_count = $query->rows; |
964
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
Count the number of rows returned. |
966
|
|
|
|
|
|
|
Returns undefined if the number is unknown. |
967
|
|
|
|
|
|
|
This uses the DBI C method which is unreliable in some situations (See Lrows|DBI/"rows">). |
968
|
|
|
|
|
|
|
|
969
|
|
|
|
|
|
|
=cut |
970
|
|
|
|
|
|
|
|
971
|
|
|
|
|
|
|
sub rows { |
972
|
1
|
|
|
1
|
1
|
3
|
my $me = shift; |
973
|
1
|
|
|
|
|
4
|
$me->sql; # Ensure the Row_Count is cleared if needed |
974
|
1
|
50
|
|
|
|
20
|
$me->{DBO}{dbd_class}->_rows($me) unless defined $me->{Row_Count}; |
975
|
1
|
|
|
|
|
8
|
$me->{Row_Count}; |
976
|
|
|
|
|
|
|
} |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
=head3 C |
979
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
my $row_count = $query->count_rows; |
981
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
Count the number of rows that would be returned. |
983
|
|
|
|
|
|
|
Returns undefined if there is an error. |
984
|
|
|
|
|
|
|
|
985
|
|
|
|
|
|
|
=cut |
986
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
sub count_rows { |
988
|
2
|
|
|
2
|
1
|
4
|
my $me = shift; |
989
|
2
|
|
|
|
|
12
|
local $me->{Config}{CalcFoundRows} = 0; |
990
|
2
|
|
|
|
|
7
|
my $old_sb = delete $me->{build_data}{Show_Bind}; |
991
|
2
|
|
|
|
|
5
|
$me->{build_data}{show} = '1'; |
992
|
|
|
|
|
|
|
|
993
|
2
|
|
|
|
|
10
|
my $sql = 'SELECT COUNT(*) FROM ('.$me->{DBO}{dbd_class}->_build_sql_select($me).') t'; |
994
|
2
|
|
|
|
|
13
|
my($count) = $me->{DBO}{dbd_class}->_selectrow_array($me, $sql, undef, |
995
|
|
|
|
|
|
|
$me->{DBO}{dbd_class}->_bind_params_select($me)); |
996
|
|
|
|
|
|
|
|
997
|
2
|
50
|
|
|
|
1235
|
$me->{build_data}{Show_Bind} = $old_sb if $old_sb; |
998
|
2
|
|
|
|
|
6
|
undef $me->{build_data}{show}; |
999
|
2
|
|
|
|
|
11
|
return $count; |
1000
|
|
|
|
|
|
|
} |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
=head3 C |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
$query->config(CalcFoundRows => 1); # Only applicable to MySQL |
1005
|
|
|
|
|
|
|
my $total_rows = $query->found_rows; |
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
Return the number of rows that would have been returned if there was no limit clause. Before runnning the query the C config option can be enabled for improved performance on supported databases. |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
Returns undefined if there is an error or is unable to determine the number of found rows. |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
=cut |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
sub found_rows { |
1014
|
1
|
|
|
1
|
1
|
3
|
my $me = shift; |
1015
|
1
|
50
|
|
|
|
16
|
$me->{DBO}{dbd_class}->_calc_found_rows($me) unless defined $me->{Found_Rows}; |
1016
|
1
|
|
|
|
|
5
|
$me->{Found_Rows}; |
1017
|
|
|
|
|
|
|
} |
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
=head3 C |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
my $sql = $query->sql; |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
Returns the SQL statement string. |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
=cut |
1026
|
|
|
|
|
|
|
|
1027
|
|
|
|
|
|
|
sub _search_where_chunk { |
1028
|
157
|
100
|
|
|
|
675
|
map { |
1029
|
163
|
|
|
163
|
|
382
|
ref $_->[0] eq 'ARRAY' ? _search_where_chunk(@$_) : ($_->[1], $_->[4]) |
1030
|
|
|
|
|
|
|
} @_ |
1031
|
|
|
|
|
|
|
} |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
our @_RECURSIVE_SQ; |
1034
|
|
|
|
|
|
|
sub sql { |
1035
|
132
|
|
|
132
|
1
|
173
|
my $me = shift; |
1036
|
|
|
|
|
|
|
# Check for changes to subqueries and recursion |
1037
|
132
|
50
|
|
|
|
323
|
croak 'Recursive subquery found' if grep $me eq $_, @_RECURSIVE_SQ; |
1038
|
132
|
|
|
|
|
340
|
local @_RECURSIVE_SQ = (@_RECURSIVE_SQ, $me); |
1039
|
132
|
|
|
|
|
166
|
for my $fld (@{$me->{build_data}{Showing}}) { |
|
132
|
|
|
|
|
394
|
|
1040
|
149
|
50
|
100
|
|
|
476
|
if (ref $fld eq 'ARRAY' and @{$fld->[0]} == 1 and _isa($fld->[0][0], 'DBIx::DBO::Query')) { |
|
118
|
|
66
|
|
|
1043
|
|
1041
|
0
|
|
|
|
|
0
|
my $sq = $fld->[0][0]; |
1042
|
0
|
0
|
0
|
|
|
0
|
if ($sq->sql ne ($me->{build_data}{_subqueries}{$sq} ||= '')) { |
1043
|
0
|
|
|
|
|
0
|
undef $me->{sql}; |
1044
|
0
|
|
|
|
|
0
|
undef $me->{build_data}{show}; |
1045
|
|
|
|
|
|
|
} |
1046
|
|
|
|
|
|
|
} |
1047
|
|
|
|
|
|
|
} |
1048
|
132
|
|
|
|
|
210
|
for my $sq (@{$me->{Tables}}) { |
|
132
|
|
|
|
|
275
|
|
1049
|
146
|
50
|
|
|
|
562
|
if (_isa($sq, 'DBIx::DBO::Query')) { |
1050
|
0
|
0
|
0
|
|
|
0
|
if ($sq->sql ne ($me->{build_data}{_subqueries}{$sq} ||= '')) { |
1051
|
0
|
|
|
|
|
0
|
undef $me->{sql}; |
1052
|
0
|
|
|
|
|
0
|
undef $me->{build_data}{from}; |
1053
|
|
|
|
|
|
|
} |
1054
|
|
|
|
|
|
|
} |
1055
|
|
|
|
|
|
|
} |
1056
|
132
|
100
|
|
|
|
214
|
for my $w (map { $_ ? _search_where_chunk(@$_) : () } @{$me->{build_data}{Join_On}}) { |
|
146
|
|
|
|
|
415
|
|
|
132
|
|
|
|
|
518
|
|
1057
|
50
|
50
|
66
|
|
|
169
|
if (@$w == 1 and _isa($w->[0], 'DBIx::DBO::Query')) { |
1058
|
0
|
|
|
|
|
0
|
my $sq = $w->[0]; |
1059
|
0
|
0
|
0
|
|
|
0
|
if ($sq->sql ne ($me->{build_data}{_subqueries}{$sq} ||= '')) { |
1060
|
0
|
|
|
|
|
0
|
undef $me->{sql}; |
1061
|
0
|
|
|
|
|
0
|
undef $me->{build_data}{from}; |
1062
|
|
|
|
|
|
|
} |
1063
|
|
|
|
|
|
|
} |
1064
|
|
|
|
|
|
|
} |
1065
|
132
|
|
|
|
|
380
|
for my $w (_search_where_chunk(@{$me->{build_data}{Where_Data}})) { |
|
132
|
|
|
|
|
628
|
|
1066
|
228
|
50
|
66
|
|
|
1642
|
if (@$w == 1 and _isa($w->[0], 'DBIx::DBO::Query')) { |
1067
|
0
|
|
|
|
|
0
|
my $sq = $w->[0]; |
1068
|
0
|
0
|
0
|
|
|
0
|
if ($sq->sql ne ($me->{build_data}{_subqueries}{$sq} ||= '')) { |
1069
|
0
|
|
|
|
|
0
|
undef $me->{sql}; |
1070
|
0
|
|
|
|
|
0
|
undef $me->{build_data}{where}; |
1071
|
|
|
|
|
|
|
} |
1072
|
|
|
|
|
|
|
} |
1073
|
|
|
|
|
|
|
} |
1074
|
132
|
100
|
|
|
|
784
|
$me->{sql} || $me->_build_sql; |
1075
|
|
|
|
|
|
|
} |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
sub _build_sql { |
1078
|
31
|
|
|
31
|
|
49
|
my $me = shift; |
1079
|
31
|
|
|
|
|
254
|
undef $me->{sth}; |
1080
|
31
|
|
|
|
|
465
|
undef $me->{hash}; |
1081
|
31
|
|
|
|
|
62
|
undef $me->{Row_Count}; |
1082
|
31
|
|
|
|
|
275
|
undef $me->{Found_Rows}; |
1083
|
31
|
|
|
|
|
93
|
delete $me->{cache}; |
1084
|
31
|
|
|
|
|
332
|
$me->{Active} = 0; |
1085
|
31
|
100
|
|
|
|
98
|
if (defined $me->{Row}) { |
1086
|
19
|
50
|
|
|
|
31
|
if (SvREFCNT(${$me->{Row}}) > 1) { |
|
19
|
|
|
|
|
106
|
|
1087
|
0
|
|
|
|
|
0
|
$me->{Row}->_detach; |
1088
|
|
|
|
|
|
|
} else { |
1089
|
19
|
|
|
|
|
31
|
undef ${$me->{Row}}->{array}; |
|
19
|
|
|
|
|
51
|
|
1090
|
19
|
|
|
|
|
37
|
undef %{$me->{Row}}; |
|
19
|
|
|
|
|
89
|
|
1091
|
|
|
|
|
|
|
|
1092
|
19
|
|
|
|
|
124
|
$me->{sql} = $me->{DBO}{dbd_class}->_build_sql_select($me, $me->{build_data}); |
1093
|
19
|
|
|
|
|
82
|
$me->{Row}{from} = $me->{DBO}{dbd_class}->_build_from($me, $me->{build_data}); |
1094
|
19
|
|
|
|
|
93
|
$me->{Row}->_copy_build_data; |
1095
|
19
|
|
|
|
|
145
|
return $me->{sql}; |
1096
|
|
|
|
|
|
|
} |
1097
|
|
|
|
|
|
|
} |
1098
|
12
|
|
|
|
|
16
|
undef @{$me->{Columns}}; |
|
12
|
|
|
|
|
42
|
|
1099
|
|
|
|
|
|
|
|
1100
|
12
|
|
|
|
|
267
|
$me->{sql} = $me->{DBO}{dbd_class}->_build_sql_select($me); |
1101
|
|
|
|
|
|
|
} |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
# Get the DBI statement handle for the query. |
1104
|
|
|
|
|
|
|
# It may not have been executed yet. |
1105
|
|
|
|
|
|
|
sub _sth { |
1106
|
49
|
|
|
49
|
|
69
|
my $me = shift; |
1107
|
|
|
|
|
|
|
# Ensure the sql is rebuilt if needed |
1108
|
49
|
|
|
|
|
106
|
my $sql = $me->sql; |
1109
|
49
|
|
66
|
|
|
316
|
$me->{sth} ||= $me->rdbh->prepare($sql); |
1110
|
|
|
|
|
|
|
} |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=head3 C |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
$query->update(department => 'Tech'); |
1115
|
|
|
|
|
|
|
$query->update(salary => { FUNC => '? * 1.10', COL => 'salary' }); # 10% raise |
1116
|
|
|
|
|
|
|
|
1117
|
|
|
|
|
|
|
Updates every row in the query with the new values specified. |
1118
|
|
|
|
|
|
|
Returns the number of rows updated or C<'0E0'> for no rows to ensure the value is true, |
1119
|
|
|
|
|
|
|
and returns false if there was an error. |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
=cut |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
sub update { |
1124
|
2
|
|
|
2
|
1
|
766
|
my $me = shift; |
1125
|
2
|
|
|
|
|
20
|
my @update = $me->{DBO}{dbd_class}->_parse_set($me, @_); |
1126
|
2
|
|
|
|
|
16
|
my $sql = $me->{DBO}{dbd_class}->_build_sql_update($me, @update); |
1127
|
2
|
|
|
|
|
18
|
$me->{DBO}{dbd_class}->_do($me, $sql, undef, $me->{DBO}{dbd_class}->_bind_params_update($me)); |
1128
|
|
|
|
|
|
|
} |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
=head3 C |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
$query->finish; |
1133
|
|
|
|
|
|
|
|
1134
|
|
|
|
|
|
|
Calls Lfinish|DBI/"finish"> on the statement handle, if it's active. |
1135
|
|
|
|
|
|
|
Restarts cached queries from the first row (if created using the C config). |
1136
|
|
|
|
|
|
|
This ensures that the next call to L will return the first row from the query. |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
=cut |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
sub finish { |
1141
|
18
|
|
|
18
|
1
|
45
|
my $me = shift; |
1142
|
18
|
100
|
|
|
|
62
|
if (defined $me->{Row}) { |
1143
|
6
|
50
|
|
|
|
15
|
if (SvREFCNT(${$me->{Row}}) > 1) { |
|
6
|
|
|
|
|
31
|
|
1144
|
0
|
|
|
|
|
0
|
$me->{Row}->_detach; |
1145
|
|
|
|
|
|
|
} else { |
1146
|
6
|
|
|
|
|
9
|
undef ${$me->{Row}}{array}; |
|
6
|
|
|
|
|
28
|
|
1147
|
6
|
|
|
|
|
14
|
${$me->{Row}}{hash} = {}; |
|
6
|
|
|
|
|
22
|
|
1148
|
|
|
|
|
|
|
} |
1149
|
|
|
|
|
|
|
} |
1150
|
18
|
100
|
|
|
|
67
|
if (exists $me->{cache}) { |
1151
|
5
|
|
|
|
|
29
|
$me->{cache}{idx} = 0; |
1152
|
|
|
|
|
|
|
} else { |
1153
|
13
|
50
|
33
|
|
|
52
|
$me->{sth}->finish if $me->{sth} and $me->{sth}{Active}; |
1154
|
13
|
|
|
|
|
54
|
$me->{Active} = 0; |
1155
|
|
|
|
|
|
|
} |
1156
|
|
|
|
|
|
|
} |
1157
|
|
|
|
|
|
|
|
1158
|
|
|
|
|
|
|
=head2 Common Methods |
1159
|
|
|
|
|
|
|
|
1160
|
|
|
|
|
|
|
These methods are accessible from all DBIx::DBO* objects. |
1161
|
|
|
|
|
|
|
|
1162
|
|
|
|
|
|
|
=head3 C |
1163
|
|
|
|
|
|
|
|
1164
|
|
|
|
|
|
|
The C object. |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
=head3 C |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
The I C handle. |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
=head3 C |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
The I C handle, or if there is no I connection, the I C handle. |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
=cut |
1175
|
|
|
|
|
|
|
|
1176
|
5
|
|
|
5
|
1
|
35
|
sub dbo { $_[0]{DBO} } |
1177
|
2
|
|
|
2
|
1
|
12
|
sub dbh { $_[0]{DBO}->dbh } |
1178
|
140
|
|
|
140
|
1
|
524
|
sub rdbh { $_[0]{DBO}->rdbh } |
1179
|
|
|
|
|
|
|
|
1180
|
|
|
|
|
|
|
=head3 C |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
$query_setting = $query->config($option); |
1183
|
|
|
|
|
|
|
$query->config($option => $query_setting); |
1184
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
Get or set this C object's config settings. When setting an option, the previous value is returned. When getting an option's value, if the value is undefined, the L's value is returned. |
1186
|
|
|
|
|
|
|
|
1187
|
|
|
|
|
|
|
See: L. |
1188
|
|
|
|
|
|
|
|
1189
|
|
|
|
|
|
|
=cut |
1190
|
|
|
|
|
|
|
|
1191
|
|
|
|
|
|
|
sub config { |
1192
|
220
|
|
|
220
|
1
|
15397
|
my $me = shift; |
1193
|
220
|
|
|
|
|
312
|
my $opt = shift; |
1194
|
220
|
100
|
50
|
|
|
664
|
return $me->{DBO}{dbd_class}->_set_config($me->{Config} ||= {}, $opt, shift) if @_; |
1195
|
192
|
|
100
|
|
|
1231
|
$me->{DBO}{dbd_class}->_get_config($opt, $me->{Config} ||= {}, $me->{DBO}{Config}, \%DBIx::DBO::Config); |
1196
|
|
|
|
|
|
|
} |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
sub STORABLE_freeze { |
1199
|
5
|
|
|
5
|
0
|
12464
|
my($me, $cloning) = @_; |
1200
|
5
|
100
|
|
|
|
125
|
return unless defined $me->{sth}; |
1201
|
|
|
|
|
|
|
|
1202
|
2
|
|
|
|
|
5
|
local $me->{sth}; |
1203
|
2
|
|
|
|
|
5
|
local $me->{Row}; |
1204
|
2
|
50
|
|
|
|
7
|
local $me->{hash} unless exists $me->{cache}; |
1205
|
2
|
50
|
|
|
|
7
|
local $me->{Active} = 0 unless exists $me->{cache}; |
1206
|
2
|
50
|
|
|
|
8
|
local $me->{cache}{idx} = 0 if exists $me->{cache}; |
1207
|
2
|
|
|
|
|
5
|
return Storable::nfreeze($me); |
1208
|
|
|
|
|
|
|
} |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
sub STORABLE_thaw { |
1211
|
2
|
|
|
2
|
0
|
883
|
my($me, $cloning, @frozen) = @_; |
1212
|
2
|
|
|
|
|
5
|
%$me = %{ Storable::thaw(@frozen) }; |
|
2
|
|
|
|
|
8
|
|
1213
|
|
|
|
|
|
|
} |
1214
|
|
|
|
|
|
|
|
1215
|
|
|
|
|
|
|
sub DESTROY { |
1216
|
15
|
|
|
15
|
|
1551
|
undef %{$_[0]}; |
|
15
|
|
|
|
|
281
|
|
1217
|
|
|
|
|
|
|
} |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
1; |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
__END__ |