Newer Older
664 lines | 17.83kb
packaging one directory
yuki-kimoto authored on 2009-11-16
1
package DBIx::Custom::SQL::Template;
2
use Object::Simple;
3

            
update document
yuki-kimoto authored on 2009-11-17
4
use strict;
5
use warnings;
packaging one directory
yuki-kimoto authored on 2009-11-16
6
use Carp 'croak';
7

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
8
use DBIx::Custom::Query;
9

            
10
# Accessor is created by Object::Simple.
packaging one directory
yuki-kimoto authored on 2009-11-16
11

            
12
### Class-Object accessors
13

            
14
# Tag start
15
sub tag_start   : ClassObjectAttr {
16
    initialize => {default => '{', clone => 'scalar'}
17
}
18

            
19
# Tag end
20
sub tag_end     : ClassObjectAttr {
21
    initialize => {default => '}', clone => 'scalar'}
22
}
23

            
24
# Tag syntax
25
sub tag_syntax  : ClassObjectAttr {
26
    initialize => {default => <<'EOS', clone => 'scalar'}}
27
[tag]                     [expand]
28
{? name}                  ?
29
{= name}                  name = ?
30
{<> name}                 name <> ?
31

            
32
{< name}                  name < ?
33
{> name}                  name > ?
34
{>= name}                 name >= ?
35
{<= name}                 name <= ?
36

            
37
{like name}               name like ?
38
{in name number}          name in [?, ?, ..]
39

            
40
{insert key1 key2} (key1, key2) values (?, ?)
41
{update key1 key2}    set key1 = ?, key2 = ?
42
EOS
43

            
44
# Tag processors
45
sub tag_processors : ClassObjectAttr {
46
    type => 'hash',
47
    deref => 1,
48
    initialize => {
49
        clone => 'hash', 
50
        default => sub {{
cleanup and update docment
yuki-kimoto authored on 2009-11-19
51
            '?'             => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
52
            '='             => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
53
            '<>'            => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
54
            '>'             => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
55
            '<'             => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
56
            '>='            => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
57
            '<='            => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
58
            'like'          => \&DBIx::Custom::SQL::Template::TagProcessors::expand_basic_tag,
59
            'in'            => \&DBIx::Custom::SQL::Template::TagProcessors::expand_in_tag,
60
            'insert'        => \&DBIx::Custom::SQL::Template::TagProcessors::expand_insert_tag,
61
            'update'    => \&DBIx::Custom::SQL::Template::TagProcessors::expand_update_tag
packaging one directory
yuki-kimoto authored on 2009-11-16
62
        }}
63
    }
64
}
65

            
66
# Add Tag processor
67
sub add_tag_processor {
68
    my $invocant = shift;
69
    my $tag_processors = ref $_[0] eq 'HASH' ? $_[0] : {@_};
70
    $invocant->tag_processors(%{$invocant->tag_processors}, %{$tag_processors});
71
    return $invocant;
72
}
73

            
74
# Clone
75
sub clone {
76
    my $self = shift;
77
    my $new = $self->new;
78
    
79
    $new->tag_start($self->tag_start);
80
    $new->tag_end($self->tag_end);
81
    $new->tag_syntax($self->tag_syntax);
82
    $new->tag_processors({%{$self->tag_processors || {}}});
83
    
84
    return $new;
85
}
86

            
87

            
88
### Object Methods
89

            
90
# Create Query
91
sub create_query {
92
    my ($self, $template)  = @_;
93
    
94
    # Parse template
95
    my $tree = $self->_parse_template($template);
96
    
97
    # Build query
98
    my $query = $self->_build_query($tree);
99
    
100
    return $query;
101
}
102

            
103
# Parse template
104
sub _parse_template {
105
    my ($self, $template) = @_;
106
    $template ||= '';
107
    
108
    my $tree = [];
109
    
110
    # Tags
111
    my $tag_start = quotemeta $self->tag_start;
112
    my $tag_end   = quotemeta $self->tag_end;
113
    
114
    # Tokenize
115
    my $state = 'text';
116
    
117
    # Save original template
118
    my $original_template = $template;
119
    
120
    # Parse template
121
    while ($template =~ s/([^$tag_start]*?)$tag_start([^$tag_end].*?)$tag_end//sm) {
122
        my $text = $1;
123
        my $tag  = $2;
124
        
125
        # Parse tree
126
        push @$tree, {type => 'text', tag_args => [$text]} if $text;
127
        
128
        if ($tag) {
129
            # Get tag name and arguments
130
            my ($tag_name, @tag_args) = split /\s+/, $tag;
131
            
132
            # Tag processor is exist?
133
            unless ($self->tag_processors->{$tag_name}) {
134
                my $tag_syntax = $self->tag_syntax;
135
                croak("Tag '{$tag}' in SQL template is not exist.\n\n" .
136
                      "<SQL template tag syntax>\n" .
137
                      "$tag_syntax\n" .
138
                      "<Your SQL template>\n" .
139
                      "$original_template\n\n");
140
            }
141
            
142
            # Check tag arguments
143
            foreach my $tag_arg (@tag_args) {
144
                # Cannot cantain placehosder '?'
145
                croak("Tag '{t }' arguments cannot contain '?'")
146
                  if $tag_arg =~ /\?/;
147
            }
148
            
149
            # Add tag to parsing tree
150
            push @$tree, {type => 'tag', tag_name => $tag_name, tag_args => [@tag_args]};
151
        }
152
    }
153
    
154
    # Add text to parsing tree 
155
    push @$tree, {type => 'text', tag_args => [$template]} if $template;
156
    
157
    return $tree;
158
}
159

            
160
# Build SQL from parsing tree
161
sub _build_query {
162
    my ($self, $tree) = @_;
163
    
164
    # SQL
165
    my $sql = '';
166
    
167
    # All parameter key infomation
168
    my $all_key_infos = [];
169
    
170
    # Build SQL 
171
    foreach my $node (@$tree) {
172
        
173
        # Get type, tag name, and arguments
174
        my $type     = $node->{type};
175
        my $tag_name = $node->{tag_name};
176
        my $tag_args = $node->{tag_args};
177
        
178
        # Text
179
        if ($type eq 'text') {
180
            # Join text
181
            $sql .= $tag_args->[0];
182
        }
183
        
184
        # Tag
185
        elsif ($type eq 'tag') {
186
            
187
            # Get tag processor
188
            my $tag_processor = $self->tag_processors->{$tag_name};
189
            
190
            # Tag processor is code ref?
191
            croak("Tag processor '$tag_name' must be code reference")
192
              unless ref $tag_processor eq 'CODE';
193
            
194
            # Expand tag using tag processor
195
            my ($expand, $key_infos)
196
              = $tag_processor->($tag_name, $tag_args);
197
            
198
            # Check tag processor return value
199
            croak("Tag processor '$tag_name' must return (\$expand, \$key_infos)")
200
              if !defined $expand || ref $key_infos ne 'ARRAY';
201
            
202
            # Check placeholder count
203
            croak("Placeholder count in SQL created by tag processor '$tag_name' " .
204
                  "must be same as key informations count")
205
              unless $self->_placeholder_count($expand) eq @$key_infos;
206
            
207
            # Add key information
208
            push @$all_key_infos, @$key_infos;
209
            
210
            # Join expand tag to SQL
211
            $sql .= $expand;
212
        }
213
    }
214
    
215
    # Add semicolon
216
    $sql .= ';' unless $sql =~ /;$/;
217
    
218
    # Query
cleanup and update docment
yuki-kimoto authored on 2009-11-19
219
    my $query = DBIx::Custom::Query->new(sql => $sql, key_infos => $all_key_infos);
packaging one directory
yuki-kimoto authored on 2009-11-16
220
    
221
    return $query;
222
}
223

            
224
# Get placeholder count
225
sub _placeholder_count {
226
    my ($self, $expand) = @_;
227
    $expand ||= '';
228
    
229
    my $count = 0;
230
    my $pos   = -1;
231
    while (($pos = index($expand, '?', $pos + 1)) != -1) {
232
        $count++;
233
    }
234
    return $count;
235
}
236

            
237
Object::Simple->build_class;
238

            
239

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
240
package DBIx::Custom::SQL::Template::TagProcessors;
241

            
packaging one directory
yuki-kimoto authored on 2009-11-16
242
use strict;
243
use warnings;
244
use Carp 'croak';
245

            
246
# Expand tag '?', '=', '<>', '>', '<', '>=', '<=', 'like'
247
sub expand_basic_tag {
248
    my ($tag_name, $tag_args) = @_;
249
    my $original_key = $tag_args->[0];
250
    
251
    # Key is not exist
252
    croak("You must be pass key as argument to tag '{$tag_name }'")
253
      if !$original_key;
254
    
255
    # Expanded tag
256
    my $expand = $tag_name eq '?'
257
               ? '?'
258
               : "$original_key $tag_name ?";
259
    
260
    # Get table and clumn name
261
    my ($table, $column) = get_table_and_column($original_key);
262
    
263
    # Parameter key infomation
264
    my $key_info = {};
265
    
266
    # Original key
267
    $key_info->{original_key} = $original_key;
268
    
269
    # Table
270
    $key_info->{table}  = $table;
271
    
272
    # Column name
273
    $key_info->{column} = $column;
274
    
275
    # Access keys
276
    my $access_keys = [];
277
    push @$access_keys, [$original_key];
278
    push @$access_keys, [$table, $column] if $table && $column;
279
    $key_info->{access_keys} = $access_keys;
280
    
281
    # Add parameter key information
282
    my $key_infos = [];
283
    push @$key_infos, $key_info;
284
    
285
    return ($expand, $key_infos);
286
}
287

            
288
# Expand tag 'in'
289
sub expand_in_tag {
290
    my ($tag_name, $tag_args) = @_;
291
    my ($original_key, $placeholder_count) = @$tag_args;
292
    
293
    # Key must be specified
294
    croak("You must be pass key as first argument of tag '{$tag_name }'\n" . 
295
          "Usage: {$tag_name \$key \$placeholder_count}")
296
      unless $original_key;
297
      
298
    
299
    # Place holder count must be specified
300
    croak("You must be pass placeholder count as second argument of tag '{$tag_name }'\n" . 
301
          "Usage: {$tag_name \$key \$placeholder_count}")
302
      if !$placeholder_count || $placeholder_count =~ /\D/;
303

            
304
    # Expand tag
305
    my $expand = "$original_key $tag_name (";
306
    for (my $i = 0; $i < $placeholder_count; $i++) {
307
        $expand .= '?, ';
308
    }
309
    
310
    $expand =~ s/, $//;
311
    $expand .= ')';
312
    
313
    # Get table and clumn name
314
    my ($table, $column) = get_table_and_column($original_key);
315
    
316
    # Create parameter key infomations
317
    my $key_infos = [];
318
    for (my $i = 0; $i < $placeholder_count; $i++) {
319
        # Parameter key infomation
320
        my $key_info = {};
321
        
322
        # Original key
323
        $key_info->{original_key} = $original_key;
324
        
325
        # Table
326
        $key_info->{table}   = $table;
327
        
328
        # Column name
329
        $key_info->{column}  = $column;
330
        
331
        # Access keys
332
        my $access_keys = [];
333
        push @$access_keys, [$original_key, [$i]];
334
        push @$access_keys, [$table, $column, [$i]] if $table && $column;
335
        $key_info->{access_keys} = $access_keys;
336
        
337
        # Add parameter key infos
338
        push @$key_infos, $key_info;
339
    }
340
    
341
    return ($expand, $key_infos);
342
}
343

            
344
# Get table and column
345
sub get_table_and_column {
346
    my $key = shift;
347
    $key ||= '';
348
    
349
    return ('', $key) unless $key =~ /\./;
350
    
351
    my ($table, $column) = split /\./, $key;
352
    
353
    return ($table, $column);
354
}
355

            
356
# Expand tag 'insert'
357
sub expand_insert_tag {
358
    my ($tag_name, $tag_args) = @_;
359
    my $original_keys = $tag_args;
360
    
361
    # Insert key (k1, k2, k3, ..)
362
    my $insert_keys = '(';
363
    
364
    # placeholder (?, ?, ?, ..)
365
    my $place_holders = '(';
366
    
367
    foreach my $original_key (@$original_keys) {
368
        # Get table and column
369
        my ($table, $column) = get_table_and_column($original_key);
370
        
371
        # Join insert column
372
        $insert_keys   .= "$column, ";
373
        
374
        # Join place holder
375
        $place_holders .= "?, ";
376
    }
377
    
378
    # Delete last ', '
379
    $insert_keys =~ s/, $//;
380
    
381
    # Close 
382
    $insert_keys .= ')';
383
    $place_holders =~ s/, $//;
384
    $place_holders .= ')';
385
    
386
    # Expand tag
387
    my $expand = "$insert_keys values $place_holders";
388
    
389
    # Create parameter key infomations
390
    my $key_infos = [];
391
    foreach my $original_key (@$original_keys) {
392
        # Get table and clumn name
393
        my ($table, $column) = get_table_and_column($original_key);
394
        
395
        # Parameter key infomation
396
        my $key_info = {};
397
        
398
        # Original key
399
        $key_info->{original_key} = $original_key;
400
        
401
        # Table
402
        $key_info->{table}   = $table;
403
        
404
        # Column name
405
        $key_info->{column}  = $column;
406
        
407
        # Access keys
408
        my $access_keys = [];
409
        push @$access_keys, ['#insert', $original_key];
410
        push @$access_keys, ['#insert', $table, $column] if $table && $column;
411
        push @$access_keys, [$original_key];
412
        push @$access_keys, [$table, $column] if $table && $column;
413
        $key_info->{access_keys} = $access_keys;
414
        
415
        # Add parameter key infos
416
        push @$key_infos, $key_info;
417
    }
418
    
419
    return ($expand, $key_infos);
420
}
421

            
422
# Expand tag 'update'
423
sub expand_update_tag {
424
    my ($tag_name, $tag_args) = @_;
425
    my $original_keys = $tag_args;
426
    
427
    # Expanded tag
428
    my $expand = 'set ';
429
    
430
    # 
431
    foreach my $original_key (@$original_keys) {
432
        # Get table and clumn name
433
        my ($table, $column) = get_table_and_column($original_key);
434

            
435
        # Join key and placeholder
436
        $expand .= "$column = ?, ";
437
    }
438
    
439
    # Delete last ', '
440
    $expand =~ s/, $//;
441
    
442
    # Create parameter key infomations
443
    my $key_infos = [];
444
    foreach my $original_key (@$original_keys) {
445
        # Get table and clumn name
446
        my ($table, $column) = get_table_and_column($original_key);
447
        
448
        # Parameter key infomation
449
        my $key_info = {};
450
        
451
        # Original key
452
        $key_info->{original_key} = $original_key;
453
        
454
        # Table
455
        $key_info->{table}  = $table;
456
        
457
        # Column name
458
        $key_info->{column} = $column;
459
        
460
        # Access keys
461
        my $access_keys = [];
462
        push @$access_keys, ['#update', $original_key];
463
        push @$access_keys, ['#update', $table, $column] if $table && $column;
464
        push @$access_keys, [$original_key];
465
        push @$access_keys, [$table, $column] if $table && $column;
466
        $key_info->{access_keys} = $access_keys;
467
        
468
        # Add parameter key infos
469
        push @$key_infos, $key_info;
470
    }
471
    
472
    return ($expand, $key_infos);
473
}
474

            
475
1;
476

            
477
=head1 NAME
478

            
update document
yuki-kimoto authored on 2009-11-17
479
DBIx::Custom::SQL::Template - DBIx::Custom SQL Template
packaging one directory
yuki-kimoto authored on 2009-11-16
480

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
481
=head1 Synopsis
packaging one directory
yuki-kimoto authored on 2009-11-16
482
    
483
    my $sql_tmpl = DBIx::Custom::SQL::Template->new;
484
    
485
    my $tmpl   = "select from table {= k1} && {<> k2} || {like k3}";
486
    my $param = {k1 => 1, k2 => 2, k3 => 3};
487
    
488
    my $query = $sql_template->create_query($tmpl);
489

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
490
=head1 Accessors
packaging one directory
yuki-kimoto authored on 2009-11-16
491

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
492
=head2 tag_processors
packaging one directory
yuki-kimoto authored on 2009-11-16
493

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
494
Set and get tag processors
packaging one directory
yuki-kimoto authored on 2009-11-16
495

            
version 0.0901
yuki-kimoto authored on 2009-12-17
496
    $sql_tmpl       = $sql_tmpl->tag_processors($name1 => $tag_processor1
497
                                                $name2 => $tag_processor2);
498
    $tag_processors = $sql_tmpl->tag_processors;
packaging one directory
yuki-kimoto authored on 2009-11-16
499

            
500
=head2 tag_start
501

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
502
Set and get start tag
503
    
version 0.0901
yuki-kimoto authored on 2009-12-17
504
    $sql_tmpl  = $sql_tmpl->tag_start('{');
505
    $tag_start = $sql_tmpl->tag_start;
packaging one directory
yuki-kimoto authored on 2009-11-16
506

            
version 0.0901
yuki-kimoto authored on 2009-12-17
507
tag_start default is '{'
packaging one directory
yuki-kimoto authored on 2009-11-16
508

            
509
=head2 tag_end
510

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
511
Set and get end tag
512
    
version 0.0901
yuki-kimoto authored on 2009-12-17
513
    $sql_tmpl    = $sql_tmpl->tag_start('}');
514
    $tag_end = $sql_tmpl->tag_start;
packaging one directory
yuki-kimoto authored on 2009-11-16
515

            
version 0.0901
yuki-kimoto authored on 2009-12-17
516
tag_start default is '}'
packaging one directory
yuki-kimoto authored on 2009-11-16
517
    
518
=head2 tag_syntax
519
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
520
Set and get tag syntax
521
    
version 0.0901
yuki-kimoto authored on 2009-12-17
522
    $sql_tmpl   = $sql_tmpl->tag_syntax($tag_syntax);
523
    $tag_syntax = $sql_tmpl->tag_syntax;
packaging one directory
yuki-kimoto authored on 2009-11-16
524

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
525
=head1 Methods
packaging one directory
yuki-kimoto authored on 2009-11-16
526

            
527
=head2 create_query
528
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
529
Create L<DBIx::Custom::Query> object parsing SQL template
530

            
version 0.0901
yuki-kimoto authored on 2009-12-17
531
    $query = $sql_tmpl->create_query($tmpl);
packaging one directory
yuki-kimoto authored on 2009-11-16
532
    
533
    # Sample
534
    $query = $sql_tmpl->create_sql(
535
         "select * from table where {= title} && {like author} || {<= price}")
536
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
537
    # Expanded
538
    $qeury->sql : "select * from table where title = ? && author like ? price <= ?;"
539
    $query->key_infos : [['title'], ['author'], ['price']]
packaging one directory
yuki-kimoto authored on 2009-11-16
540
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
541
    # Sample with table name
packaging one directory
yuki-kimoto authored on 2009-11-16
542
    ($sql, @bind_values) = $sql_tmpl->create_sql(
543
            "select * from table where {= table.title} && {like table.author}",
544
            {table => {title => 'Perl', author => '%Taro%'}}
545
        )
546
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
547
    # Expanded
548
    $query->sql : "select * from table where table.title = ? && table.title like ?;"
549
    $query->key_infos :[ [['table.title'],['table', 'title']],
550
                         [['table.author'],['table', 'author']] ]
packaging one directory
yuki-kimoto authored on 2009-11-16
551

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
552
This method create query using by L<DBIx::Custom>.
553
query has two infomation
packaging one directory
yuki-kimoto authored on 2009-11-16
554

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
555
    1. sql       : SQL
556
    2. key_infos : Parameter access key information
packaging one directory
yuki-kimoto authored on 2009-11-16
557

            
558
=head2 add_tag_processor
559

            
560
Add tag processor
cleanup and update docment
yuki-kimoto authored on 2009-11-19
561
    
version 0.0901
yuki-kimoto authored on 2009-12-17
562
    $sql_tmpl = $sql_tmpl->add_tag_processor($tag_processor);
563

            
564
The following is add_tag_processor sample
565

            
packaging one directory
yuki-kimoto authored on 2009-11-16
566
    $sql_tmpl->add_tag_processor(
567
        '?' => sub {
568
            my ($tag_name, $tag_args) = @_;
569
            
570
            my $key1 = $tag_args->[0];
571
            my $key2 = $tag_args->[1];
572
            
573
            my $key_infos = [];
574
            
575
            # Expand tag and create key informations
576
            
577
            # Return expand tags and key informations
578
            return ($expand, $key_infos);
579
        }
580
    );
581

            
582
Tag processor recieve 2 argument
583

            
584
    1. Tag name            (?, =, <>, or etc)
585
    2. Tag arguments       (arg1 and arg2 in {tag_name arg1 arg2})
586

            
587
Tag processor return 2 value
588

            
589
    1. Expanded Tag (For exsample, '{= title}' is expanded to 'title = ?')
590
    2. Key infomations
591
    
592
You must be return expanded tag and key infomations.
593

            
594
Key information is a little complex. so I will explan this in future.
595

            
596
If you want to know more, Please see DBIx::Custom::SQL::Template source code.
597

            
598
=head2 clone
599

            
cleanup and update docment
yuki-kimoto authored on 2009-11-19
600
Clone DBIx::Custom::SQL::Template object
601

            
version 0.0901
yuki-kimoto authored on 2009-12-17
602
    $clone = $sql_tmpl->clone;
packaging one directory
yuki-kimoto authored on 2009-11-16
603
    
604
=head1 Available Tags
605
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
606
Available Tags
607

            
packaging one directory
yuki-kimoto authored on 2009-11-16
608
    [tag]            [expand]
609
    {? name}         ?
610
    {= name}         name = ?
611
    {<> name}        name <> ?
612
    
613
    {< name}         name < ?
614
    {> name}         name > ?
615
    {>= name}        name >= ?
616
    {<= name}        name <= ?
617
    
618
    {like name}      name like ?
619
    {in name}        name in [?, ?, ..]
620
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
621
    {insert}         (key1, key2, key3) values (?, ?, ?)
622
    {update}         set key1 = ?, key2 = ?, key3 = ?
packaging one directory
yuki-kimoto authored on 2009-11-16
623
    
version 0.0901
yuki-kimoto authored on 2009-12-17
624

            
625
The following is insert SQL sample
626

            
packaging one directory
yuki-kimoto authored on 2009-11-16
627
    $query = $sql_tmpl->create_sql(
628
        "insert into table {insert key1 key2}"
629
    );
version 0.0901
yuki-kimoto authored on 2009-12-17
630
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
631
    # Expanded
632
    $query->sql : "insert into table (key1, key2) values (?, ?)"
version 0.0901
yuki-kimoto authored on 2009-12-17
633

            
634
The following is update SQL sample
packaging one directory
yuki-kimoto authored on 2009-11-16
635
    
636
    $query = $sql_tmpl->create_sql(
637
        "update table {update key1 key2} where {= key3}"
638
    );
639
    
cleanup and update docment
yuki-kimoto authored on 2009-11-19
640
    # Expanded
641
    $query->sql : "update table set key1 = ?, key2 = ? where key3 = ?;"
packaging one directory
yuki-kimoto authored on 2009-11-16
642
    
643
=head1 AUTHOR
644

            
645
Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
646

            
647
Github 
648
L<http://github.com/yuki-kimoto>
649
L<http://github.com/yuki-kimoto/DBIx-Custom-SQL-Template>
650

            
651
Please let know me bag if you find
652
Please request me if you want to do something
653

            
654
=head1 COPYRIGHT & LICENSE
655

            
656
Copyright 2009 Yuki Kimoto, all rights reserved.
657

            
658
This program is free software; you can redistribute it and/or modify it
659
under the same terms as Perl itself.
660

            
661

            
662
=cut
663

            
664
1; # End of DBIx::Custom::SQL::Template