renamed default_query_filter to default_bind_filter...
...(not backword compatible)
| ... | ... |
@@ -1,4 +1,8 @@ |
| 1 | 1 |
0.1604 |
| 2 |
+ renamed default_query_filter to default_bind_filter(not backword compatible) |
|
| 3 |
+ renamed DBIx::Custom::SQLTemplate to DBIx::Custom::SQLBuilder(not backword compatible) |
|
| 4 |
+ renamed create_query to build_query(not backword compatible) |
|
| 5 |
+ renamed sql_template to sql_builder(not backword compatible) |
|
| 2 | 6 |
removed DESTROY method(not backword compatible) |
| 3 | 7 |
removed disconnect method(not backword compatible) |
| 4 | 8 |
fixed DBIx::Custom::MySQL connect_memory |
| ... | ... |
@@ -8,13 +8,13 @@ use base 'Object::Simple'; |
| 8 | 8 |
use Carp 'croak'; |
| 9 | 9 |
use DBI; |
| 10 | 10 |
use DBIx::Custom::Result; |
| 11 |
-use DBIx::Custom::SQLTemplate; |
|
| 11 |
+use DBIx::Custom::QueryBuilder; |
|
| 12 | 12 |
use DBIx::Custom::Query; |
| 13 | 13 |
use Encode qw/encode_utf8 decode_utf8/; |
| 14 | 14 |
|
| 15 | 15 |
__PACKAGE__->attr('dbh');
|
| 16 | 16 |
__PACKAGE__->attr([qw/user password data_source/]); |
| 17 |
-__PACKAGE__->attr([qw/default_query_filter default_fetch_filter/]); |
|
| 17 |
+__PACKAGE__->attr([qw/default_bind_filter default_fetch_filter/]); |
|
| 18 | 18 |
|
| 19 | 19 |
__PACKAGE__->dual_attr('filters', default => sub { {} },
|
| 20 | 20 |
inherit => 'hash_copy'); |
| ... | ... |
@@ -24,7 +24,7 @@ __PACKAGE__->register_filter( |
| 24 | 24 |
); |
| 25 | 25 |
|
| 26 | 26 |
__PACKAGE__->attr(result_class => 'DBIx::Custom::Result'); |
| 27 |
-__PACKAGE__->attr(sql_template => sub { DBIx::Custom::SQLTemplate->new });
|
|
| 27 |
+__PACKAGE__->attr(sql_builder => sub {DBIx::Custom::QueryBuilder->new});
|
|
| 28 | 28 |
|
| 29 | 29 |
__PACKAGE__->attr(cache => 1); |
| 30 | 30 |
__PACKAGE__->attr(cache_method => sub {
|
| ... | ... |
@@ -109,12 +109,12 @@ sub insert {
|
| 109 | 109 |
unless @insert_keys; |
| 110 | 110 |
|
| 111 | 111 |
# Templte for insert |
| 112 |
- my $template = "insert into $table {insert "
|
|
| 112 |
+ my $source = "insert into $table {insert "
|
|
| 113 | 113 |
. join(' ', @insert_keys) . '}';
|
| 114 |
- $template .= " $append" if $append; |
|
| 114 |
+ $source .= " $append" if $append; |
|
| 115 | 115 |
|
| 116 | 116 |
# Execute query |
| 117 |
- my $ret_val = $self->execute($template, param => $param, |
|
| 117 |
+ my $ret_val = $self->execute($source, param => $param, |
|
| 118 | 118 |
filter => $filter); |
| 119 | 119 |
|
| 120 | 120 |
return $ret_val; |
| ... | ... |
@@ -171,8 +171,8 @@ sub update {
|
| 171 | 171 |
} |
| 172 | 172 |
|
| 173 | 173 |
# Template for update |
| 174 |
- my $template = "update $table $update_clause $where_clause"; |
|
| 175 |
- $template .= " $append_statement" if $append_statement; |
|
| 174 |
+ my $source = "update $table $update_clause $where_clause"; |
|
| 175 |
+ $source .= " $append_statement" if $append_statement; |
|
| 176 | 176 |
|
| 177 | 177 |
# Rearrange parammeters |
| 178 | 178 |
foreach my $wkey (@where_keys) {
|
| ... | ... |
@@ -189,7 +189,7 @@ sub update {
|
| 189 | 189 |
} |
| 190 | 190 |
|
| 191 | 191 |
# Execute query |
| 192 |
- my $ret_val = $self->execute($template, param => $param, |
|
| 192 |
+ my $ret_val = $self->execute($source, param => $param, |
|
| 193 | 193 |
filter => $filter); |
| 194 | 194 |
|
| 195 | 195 |
return $ret_val; |
| ... | ... |
@@ -234,11 +234,11 @@ sub delete {
|
| 234 | 234 |
} |
| 235 | 235 |
|
| 236 | 236 |
# Template for delete |
| 237 |
- my $template = "delete from $table $where_clause"; |
|
| 238 |
- $template .= " $append_statement" if $append_statement; |
|
| 237 |
+ my $source = "delete from $table $where_clause"; |
|
| 238 |
+ $source .= " $append_statement" if $append_statement; |
|
| 239 | 239 |
|
| 240 | 240 |
# Execute query |
| 241 |
- my $ret_val = $self->execute($template, param => $where, |
|
| 241 |
+ my $ret_val = $self->execute($source, param => $where, |
|
| 242 | 242 |
filter => $filter); |
| 243 | 243 |
|
| 244 | 244 |
return $ret_val; |
| ... | ... |
@@ -269,82 +269,83 @@ sub select {
|
| 269 | 269 |
my $param = $args{param} || {};
|
| 270 | 270 |
|
| 271 | 271 |
# SQL template for select statement |
| 272 |
- my $template = 'select '; |
|
| 272 |
+ my $source = 'select '; |
|
| 273 | 273 |
|
| 274 | 274 |
# Column clause |
| 275 | 275 |
if (@$columns) {
|
| 276 | 276 |
foreach my $column (@$columns) {
|
| 277 |
- $template .= "$column, "; |
|
| 277 |
+ $source .= "$column, "; |
|
| 278 | 278 |
} |
| 279 |
- $template =~ s/, $/ /; |
|
| 279 |
+ $source =~ s/, $/ /; |
|
| 280 | 280 |
} |
| 281 | 281 |
else {
|
| 282 |
- $template .= '* '; |
|
| 282 |
+ $source .= '* '; |
|
| 283 | 283 |
} |
| 284 | 284 |
|
| 285 | 285 |
# Table |
| 286 |
- $template .= 'from '; |
|
| 286 |
+ $source .= 'from '; |
|
| 287 | 287 |
foreach my $table (@$tables) {
|
| 288 |
- $template .= "$table, "; |
|
| 288 |
+ $source .= "$table, "; |
|
| 289 | 289 |
} |
| 290 |
- $template =~ s/, $/ /; |
|
| 290 |
+ $source =~ s/, $/ /; |
|
| 291 | 291 |
|
| 292 | 292 |
# Where clause |
| 293 | 293 |
my @where_keys = keys %$where; |
| 294 | 294 |
if (@where_keys) {
|
| 295 |
- $template .= 'where '; |
|
| 295 |
+ $source .= 'where '; |
|
| 296 | 296 |
foreach my $where_key (@where_keys) {
|
| 297 |
- $template .= "{= $where_key} and ";
|
|
| 297 |
+ $source .= "{= $where_key} and ";
|
|
| 298 | 298 |
} |
| 299 | 299 |
} |
| 300 |
- $template =~ s/ and $//; |
|
| 300 |
+ $source =~ s/ and $//; |
|
| 301 | 301 |
|
| 302 | 302 |
# Relation |
| 303 | 303 |
if ($relation) {
|
| 304 |
- $template .= @where_keys ? "and " : "where "; |
|
| 304 |
+ $source .= @where_keys ? "and " : "where "; |
|
| 305 | 305 |
foreach my $rkey (keys %$relation) {
|
| 306 |
- $template .= "$rkey = " . $relation->{$rkey} . " and ";
|
|
| 306 |
+ $source .= "$rkey = " . $relation->{$rkey} . " and ";
|
|
| 307 | 307 |
} |
| 308 | 308 |
} |
| 309 |
- $template =~ s/ and $//; |
|
| 309 |
+ $source =~ s/ and $//; |
|
| 310 | 310 |
|
| 311 | 311 |
# Append some statement |
| 312 |
- $template .= " $append" if $append; |
|
| 312 |
+ $source .= " $append" if $append; |
|
| 313 | 313 |
|
| 314 | 314 |
# Execute query |
| 315 |
- my $result = $self->execute($template, param => $where, |
|
| 315 |
+ my $result = $self->execute($source, param => $where, |
|
| 316 | 316 |
filter => $filter); |
| 317 | 317 |
|
| 318 | 318 |
return $result; |
| 319 | 319 |
} |
| 320 | 320 |
|
| 321 |
-sub create_query {
|
|
| 322 |
- my ($self, $template) = @_; |
|
| 323 |
- |
|
| 324 |
- # Create query from SQL template |
|
| 325 |
- my $sql_template = $self->sql_template; |
|
| 321 |
+sub build_query {
|
|
| 322 |
+ my ($self, $source) = @_; |
|
| 326 | 323 |
|
| 324 |
+ # Cache |
|
| 327 | 325 |
my $cache = $self->cache; |
| 328 | 326 |
|
| 329 | 327 |
# Create query |
| 330 | 328 |
my $query; |
| 331 | 329 |
if ($cache) {
|
| 332 | 330 |
|
| 333 |
- # Cached query |
|
| 334 |
- my $q = $self->cache_method->($self, $template); |
|
| 331 |
+ # Get query |
|
| 332 |
+ my $q = $self->cache_method->($self, $source); |
|
| 335 | 333 |
|
| 336 | 334 |
# Create query |
| 337 | 335 |
$query = DBIx::Custom::Query->new($q) if $q; |
| 338 | 336 |
} |
| 339 | 337 |
|
| 340 | 338 |
unless ($query) {
|
| 339 |
+ |
|
| 340 |
+ # Create SQL object |
|
| 341 |
+ my $builder = $self->sql_builder; |
|
| 341 | 342 |
|
| 342 | 343 |
# Create query |
| 343 |
- $query = eval{$sql_template->create_query($template)};
|
|
| 344 |
+ $query = eval{$builder->build_query($source)};
|
|
| 344 | 345 |
croak($@) if $@; |
| 345 | 346 |
|
| 346 | 347 |
# Cache query |
| 347 |
- $self->cache_method->($self, $template, |
|
| 348 |
+ $self->cache_method->($self, $source, |
|
| 348 | 349 |
{sql => $query->sql,
|
| 349 | 350 |
columns => $query->columns}) |
| 350 | 351 |
if $cache; |
| ... | ... |
@@ -375,14 +376,14 @@ sub execute{
|
| 375 | 376 |
|
| 376 | 377 |
# First argument is SQL template |
| 377 | 378 |
unless (ref $query eq 'DBIx::Custom::Query') {
|
| 378 |
- my $template; |
|
| 379 |
+ my $source; |
|
| 379 | 380 |
|
| 380 | 381 |
if (ref $query eq 'ARRAY') {
|
| 381 |
- $template = $query->[0]; |
|
| 382 |
+ $source = $query->[0]; |
|
| 382 | 383 |
} |
| 383 |
- else { $template = $query }
|
|
| 384 |
+ else { $source = $query }
|
|
| 384 | 385 |
|
| 385 |
- $query = $self->create_query($template); |
|
| 386 |
+ $query = $self->build_query($source); |
|
| 386 | 387 |
} |
| 387 | 388 |
|
| 388 | 389 |
my $filter = $args{filter} || $query->filter || {};
|
| ... | ... |
@@ -398,15 +399,13 @@ sub execute{
|
| 398 | 399 |
# Return resultset if select statement is executed |
| 399 | 400 |
if ($sth->{NUM_OF_FIELDS}) {
|
| 400 | 401 |
|
| 401 |
- # Get result class |
|
| 402 |
- my $result_class = $self->result_class; |
|
| 403 |
- |
|
| 404 | 402 |
# Create result |
| 405 |
- my $result = $result_class->new({
|
|
| 406 |
- sth => $sth, |
|
| 407 |
- default_filter => $self->default_fetch_filter, |
|
| 408 |
- filters => $self->filters |
|
| 409 |
- }); |
|
| 403 |
+ my $result = $self->result_class->new( |
|
| 404 |
+ sth => $sth, |
|
| 405 |
+ default_filter => $self->default_fetch_filter, |
|
| 406 |
+ filters => $self->filters |
|
| 407 |
+ ); |
|
| 408 |
+ |
|
| 410 | 409 |
return $result; |
| 411 | 410 |
} |
| 412 | 411 |
return $affected; |
| ... | ... |
@@ -434,7 +433,7 @@ sub _build_bind_values {
|
| 434 | 433 |
$filter ||= {};
|
| 435 | 434 |
|
| 436 | 435 |
# Filter name |
| 437 |
- my $fname = $filter->{$column} || $self->default_query_filter || '';
|
|
| 436 |
+ my $fname = $filter->{$column} || $self->default_bind_filter || '';
|
|
| 438 | 437 |
|
| 439 | 438 |
my $filter_func; |
| 440 | 439 |
if ($fname) {
|
| ... | ... |
@@ -530,13 +529,13 @@ This module is not stable. Method name and implementations will be changed. |
| 530 | 529 |
filter => {tilte => 'encode_utf8'});
|
| 531 | 530 |
|
| 532 | 531 |
# Create query and execute it |
| 533 |
- my $query = $dbi->create_query( |
|
| 532 |
+ my $query = $dbi->build_query( |
|
| 534 | 533 |
"select id from books where {= author} && {like title}"
|
| 535 | 534 |
); |
| 536 | 535 |
$dbi->execute($query, param => {author => 'ken', title => '%Perl%'})
|
| 537 | 536 |
|
| 538 | 537 |
# Default filter |
| 539 |
- $dbi->default_query_filter('encode_utf8');
|
|
| 538 |
+ $dbi->default_bind_filter('encode_utf8');
|
|
| 540 | 539 |
$dbi->default_fetch_filter('decode_utf8');
|
| 541 | 540 |
|
| 542 | 541 |
# Fetch |
| ... | ... |
@@ -635,10 +634,10 @@ By default, "encode_utf8" and "decode_utf8" is registered. |
| 635 | 634 |
$encode_utf8 = $dbi->filters->{encode_utf8};
|
| 636 | 635 |
$decode_utf8 = $dbi->filters->{decode_utf8};
|
| 637 | 636 |
|
| 638 |
-=head2 C<default_query_filter> |
|
| 637 |
+=head2 C<default_bind_filter> |
|
| 639 | 638 |
|
| 640 |
- $dbi = $dbi->default_query_filter('encode_utf8');
|
|
| 641 |
- $default_query_filter = $dbi->default_query_filter |
|
| 639 |
+ $dbi = $dbi->default_bind_filter('encode_utf8');
|
|
| 640 |
+ $default_bind_filter = $dbi->default_bind_filter |
|
| 642 | 641 |
|
| 643 | 642 |
Default filter for value binding |
| 644 | 643 |
|
| ... | ... |
@@ -655,16 +654,16 @@ Default filter for fetching. |
| 655 | 654 |
$result_class = $dbi->result_class; |
| 656 | 655 |
|
| 657 | 656 |
Result class for select statement. |
| 658 |
-Default to L<DBIx::Custom::Result> |
|
| 657 |
+Default to L<DBIx::Custom::Result>. |
|
| 659 | 658 |
|
| 660 |
-=head2 C<sql_template> |
|
| 659 |
+=head2 C<sql_builder> |
|
| 661 | 660 |
|
| 662 |
- $dbi = $dbi->sql_template(DBIx::Cutom::SQLTemplate->new); |
|
| 663 |
- $sql_template = $dbi->sql_template; |
|
| 661 |
+ $dbi = $dbi->sql_builder('DBIx::Cutom::QueryBuilder);
|
|
| 662 |
+ $sql_class = $dbi->sql_builder; |
|
| 664 | 663 |
|
| 665 |
-SQLTemplate instance. sql_template attribute must be |
|
| 666 |
-the instance of L<DBIx::Cutom::SQLTemplate> subclass. |
|
| 667 |
-Default to DBIx::Cutom::SQLTemplate object |
|
| 664 |
+SQL builder. sql_builder_class must be |
|
| 665 |
+the instance of L<DBIx::Cutom::QueryBuilder> subclass |
|
| 666 |
+Default to DBIx::Custom::QueryBuilder. |
|
| 668 | 667 |
|
| 669 | 668 |
=head1 METHODS |
| 670 | 669 |
|
| ... | ... |
@@ -796,19 +795,19 @@ B<Example:> |
| 796 | 795 |
relation => {'books.id' => 'rental.book_id'}
|
| 797 | 796 |
); |
| 798 | 797 |
|
| 799 |
-=head2 C<create_query> |
|
| 798 |
+=head2 C<build_query> |
|
| 800 | 799 |
|
| 801 |
- my $query = $dbi->create_query( |
|
| 800 |
+ my $query = $dbi->build_query( |
|
| 802 | 801 |
"select * from authors where {= name} and {= age};"
|
| 803 | 802 |
); |
| 804 | 803 |
|
| 805 |
-Create the instance of L<DBIx::Custom::Query>. |
|
| 806 |
-This receive the string written by SQL template. |
|
| 804 |
+Build the instance of L<DBIx::Custom::Query> |
|
| 805 |
+using L<DBIx::Custom::QueryBuilder>. |
|
| 807 | 806 |
|
| 808 | 807 |
=head2 C<execute> |
| 809 | 808 |
|
| 810 | 809 |
$result = $dbi->execute($query, param => $params, filter => {%filter});
|
| 811 |
- $result = $dbi->execute($template, param => $params, filter => {%filter});
|
|
| 810 |
+ $result = $dbi->execute($source, param => $params, filter => {%filter});
|
|
| 812 | 811 |
|
| 813 | 812 |
Execute the instace of L<DBIx::Custom::Query> or |
| 814 | 813 |
the string written by SQL template. |
| ... | ... |
@@ -823,8 +822,6 @@ B<Example:> |
| 823 | 822 |
# do something |
| 824 | 823 |
} |
| 825 | 824 |
|
| 826 |
-See also L<DBIx::Custom::SQLTemplate> to know how to write SQL template. |
|
| 827 |
- |
|
| 828 | 825 |
=head2 C<register_filter> |
| 829 | 826 |
|
| 830 | 827 |
$dbi->register_filter(%filters); |
| ... | ... |
@@ -0,0 +1,314 @@ |
| 1 |
+package DBIx::Custom::QueryBuilder; |
|
| 2 |
+ |
|
| 3 |
+use strict; |
|
| 4 |
+use warnings; |
|
| 5 |
+ |
|
| 6 |
+use base 'Object::Simple'; |
|
| 7 |
+ |
|
| 8 |
+use Carp 'croak'; |
|
| 9 |
+use DBIx::Custom::Query; |
|
| 10 |
+use DBIx::Custom::QueryBuilder::TagProcessor; |
|
| 11 |
+ |
|
| 12 |
+__PACKAGE__->dual_attr('tag_processors', default => sub { {} }, inherit => 'hash_copy');
|
|
| 13 |
+__PACKAGE__->register_tag_processor( |
|
| 14 |
+ '?' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_placeholder_tag, |
|
| 15 |
+ '=' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 16 |
+ '<>' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 17 |
+ '>' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 18 |
+ '<' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 19 |
+ '>=' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 20 |
+ '<=' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 21 |
+ 'like' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_basic_tag, |
|
| 22 |
+ 'in' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_in_tag, |
|
| 23 |
+ 'insert' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_insert_tag, |
|
| 24 |
+ 'update' => \&DBIx::Custom::QueryBuilder::TagProcessors::expand_update_tag |
|
| 25 |
+); |
|
| 26 |
+ |
|
| 27 |
+__PACKAGE__->attr(tag_start => '{');
|
|
| 28 |
+__PACKAGE__->attr(tag_end => '}'); |
|
| 29 |
+ |
|
| 30 |
+__PACKAGE__->attr('tag_syntax' => <<'EOS');
|
|
| 31 |
+[tag] [expand] |
|
| 32 |
+{? name} ?
|
|
| 33 |
+{= name} name = ?
|
|
| 34 |
+{<> name} name <> ?
|
|
| 35 |
+ |
|
| 36 |
+{< name} name < ?
|
|
| 37 |
+{> name} name > ?
|
|
| 38 |
+{>= name} name >= ?
|
|
| 39 |
+{<= name} name <= ?
|
|
| 40 |
+ |
|
| 41 |
+{like name} name like ?
|
|
| 42 |
+{in name number} name in [?, ?, ..]
|
|
| 43 |
+ |
|
| 44 |
+{insert key1 key2} (key1, key2) values (?, ?)
|
|
| 45 |
+{update key1 key2} set key1 = ?, key2 = ?
|
|
| 46 |
+EOS |
|
| 47 |
+ |
|
| 48 |
+sub register_tag_processor {
|
|
| 49 |
+ my $self = shift; |
|
| 50 |
+ my $tag_processors = ref $_[0] eq 'HASH' ? $_[0] : {@_};
|
|
| 51 |
+ $self->tag_processors({%{$self->tag_processors}, %{$tag_processors}});
|
|
| 52 |
+ return $self; |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+sub build_query {
|
|
| 56 |
+ my ($self, $source) = @_; |
|
| 57 |
+ |
|
| 58 |
+ # Parse |
|
| 59 |
+ my $tree = $self->_parse($source); |
|
| 60 |
+ |
|
| 61 |
+ # Build query |
|
| 62 |
+ my $query = $self->_build_query($tree); |
|
| 63 |
+ |
|
| 64 |
+ return $query; |
|
| 65 |
+} |
|
| 66 |
+ |
|
| 67 |
+sub _parse {
|
|
| 68 |
+ my ($self, $source) = @_; |
|
| 69 |
+ |
|
| 70 |
+ if (ref $source eq 'ARRAY') {
|
|
| 71 |
+ $source = $source->[1]; |
|
| 72 |
+ } |
|
| 73 |
+ $source ||= ''; |
|
| 74 |
+ |
|
| 75 |
+ my $tree = []; |
|
| 76 |
+ |
|
| 77 |
+ # Tags |
|
| 78 |
+ my $tag_start = quotemeta $self->tag_start; |
|
| 79 |
+ my $tag_end = quotemeta $self->tag_end; |
|
| 80 |
+ |
|
| 81 |
+ # Tokenize |
|
| 82 |
+ my $state = 'text'; |
|
| 83 |
+ |
|
| 84 |
+ # Save original |
|
| 85 |
+ my $original = $source; |
|
| 86 |
+ |
|
| 87 |
+ # Parse |
|
| 88 |
+ while ($source =~ s/([^$tag_start]*?)$tag_start([^$tag_end].*?)$tag_end//sm) {
|
|
| 89 |
+ my $text = $1; |
|
| 90 |
+ my $tag = $2; |
|
| 91 |
+ |
|
| 92 |
+ # Parse tree |
|
| 93 |
+ push @$tree, {type => 'text', tag_args => [$text]} if $text;
|
|
| 94 |
+ |
|
| 95 |
+ if ($tag) {
|
|
| 96 |
+ # Get tag name and arguments |
|
| 97 |
+ my ($tag_name, @tag_args) = split /\s+/, $tag; |
|
| 98 |
+ |
|
| 99 |
+ # Tag processor is exist? |
|
| 100 |
+ unless ($self->tag_processors->{$tag_name}) {
|
|
| 101 |
+ my $tag_syntax = $self->tag_syntax; |
|
| 102 |
+ croak("Tag '{$tag}' is not registerd.\n\n" .
|
|
| 103 |
+ "<SQL builder syntax>\n" . |
|
| 104 |
+ "$tag_syntax\n" . |
|
| 105 |
+ "<Your source>\n" . |
|
| 106 |
+ "$original\n\n"); |
|
| 107 |
+ } |
|
| 108 |
+ |
|
| 109 |
+ # Check tag arguments |
|
| 110 |
+ foreach my $tag_arg (@tag_args) {
|
|
| 111 |
+ # Cannot cantain placehosder '?' |
|
| 112 |
+ croak("Tag '{t }' arguments cannot contain '?'")
|
|
| 113 |
+ if $tag_arg =~ /\?/; |
|
| 114 |
+ } |
|
| 115 |
+ |
|
| 116 |
+ # Add tag to parsing tree |
|
| 117 |
+ push @$tree, {type => 'tag', tag_name => $tag_name, tag_args => [@tag_args]};
|
|
| 118 |
+ } |
|
| 119 |
+ } |
|
| 120 |
+ |
|
| 121 |
+ # Add text to parsing tree |
|
| 122 |
+ push @$tree, {type => 'text', tag_args => [$source]} if $source;
|
|
| 123 |
+ |
|
| 124 |
+ return $tree; |
|
| 125 |
+} |
|
| 126 |
+ |
|
| 127 |
+sub _build_query {
|
|
| 128 |
+ my ($self, $tree) = @_; |
|
| 129 |
+ |
|
| 130 |
+ # SQL |
|
| 131 |
+ my $sql = ''; |
|
| 132 |
+ |
|
| 133 |
+ # All parameter key infomation |
|
| 134 |
+ my $all_columns = []; |
|
| 135 |
+ |
|
| 136 |
+ # Build SQL |
|
| 137 |
+ foreach my $node (@$tree) {
|
|
| 138 |
+ |
|
| 139 |
+ # Get type, tag name, and arguments |
|
| 140 |
+ my $type = $node->{type};
|
|
| 141 |
+ my $tag_name = $node->{tag_name};
|
|
| 142 |
+ my $tag_args = $node->{tag_args};
|
|
| 143 |
+ |
|
| 144 |
+ # Text |
|
| 145 |
+ if ($type eq 'text') {
|
|
| 146 |
+ # Join text |
|
| 147 |
+ $sql .= $tag_args->[0]; |
|
| 148 |
+ } |
|
| 149 |
+ |
|
| 150 |
+ # Tag |
|
| 151 |
+ elsif ($type eq 'tag') {
|
|
| 152 |
+ |
|
| 153 |
+ # Get tag processor |
|
| 154 |
+ my $tag_processor = $self->tag_processors->{$tag_name};
|
|
| 155 |
+ |
|
| 156 |
+ # Tag processor is code ref? |
|
| 157 |
+ croak("Tag processor '$tag_name' must be code reference")
|
|
| 158 |
+ unless ref $tag_processor eq 'CODE'; |
|
| 159 |
+ |
|
| 160 |
+ # Expand tag using tag processor |
|
| 161 |
+ my ($expand, $columns) = $tag_processor->($tag_name, $tag_args); |
|
| 162 |
+ |
|
| 163 |
+ # Check tag processor return value |
|
| 164 |
+ croak("Tag processor '$tag_name' must return (\$expand, \$columns)")
|
|
| 165 |
+ if !defined $expand || ref $columns ne 'ARRAY'; |
|
| 166 |
+ |
|
| 167 |
+ # Check placeholder count |
|
| 168 |
+ croak("Placeholder count in SQL created by tag processor '$tag_name' " .
|
|
| 169 |
+ "must be same as key informations count") |
|
| 170 |
+ unless $self->_placeholder_count($expand) eq @$columns; |
|
| 171 |
+ |
|
| 172 |
+ # Add key information |
|
| 173 |
+ push @$all_columns, @$columns; |
|
| 174 |
+ |
|
| 175 |
+ # Join expand tag to SQL |
|
| 176 |
+ $sql .= $expand; |
|
| 177 |
+ } |
|
| 178 |
+ } |
|
| 179 |
+ |
|
| 180 |
+ # Add semicolon |
|
| 181 |
+ $sql .= ';' unless $sql =~ /;$/; |
|
| 182 |
+ |
|
| 183 |
+ # Query |
|
| 184 |
+ my $query = DBIx::Custom::Query->new(sql => $sql, columns => $all_columns); |
|
| 185 |
+ |
|
| 186 |
+ return $query; |
|
| 187 |
+} |
|
| 188 |
+ |
|
| 189 |
+sub _placeholder_count {
|
|
| 190 |
+ my ($self, $expand) = @_; |
|
| 191 |
+ $expand ||= ''; |
|
| 192 |
+ |
|
| 193 |
+ my $count = 0; |
|
| 194 |
+ my $pos = -1; |
|
| 195 |
+ while (($pos = index($expand, '?', $pos + 1)) != -1) {
|
|
| 196 |
+ $count++; |
|
| 197 |
+ } |
|
| 198 |
+ return $count; |
|
| 199 |
+} |
|
| 200 |
+ |
|
| 201 |
+1; |
|
| 202 |
+ |
|
| 203 |
+=head1 NAME |
|
| 204 |
+ |
|
| 205 |
+DBIx::Custom::QueryBuilder - Query builder |
|
| 206 |
+ |
|
| 207 |
+=head1 SYNOPSIS |
|
| 208 |
+ |
|
| 209 |
+ my $builder = DBIx::Custom::QueryBuilder->new; |
|
| 210 |
+ |
|
| 211 |
+ my $source = "select from table {= k1} && {<> k2} || {like k3}";
|
|
| 212 |
+ my $param = {k1 => 1, k2 => 2, k3 => 3};
|
|
| 213 |
+ |
|
| 214 |
+ my $query = $sql_builder->build_query($source); |
|
| 215 |
+ |
|
| 216 |
+=head1 ATTRIBUTES |
|
| 217 |
+ |
|
| 218 |
+=head2 C<tag_processors> |
|
| 219 |
+ |
|
| 220 |
+ my $tag_processors = $builder->tag_processors; |
|
| 221 |
+ $builder = $builder->tag_processors(\%tag_processors); |
|
| 222 |
+ |
|
| 223 |
+Tag processors. |
|
| 224 |
+ |
|
| 225 |
+=head2 C<tag_start> |
|
| 226 |
+ |
|
| 227 |
+ my $tag_start = $builder->tag_start; |
|
| 228 |
+ $builder = $builder->tag_start('{');
|
|
| 229 |
+ |
|
| 230 |
+String of tag start. |
|
| 231 |
+Default to '{'
|
|
| 232 |
+ |
|
| 233 |
+=head2 C<tag_end> |
|
| 234 |
+ |
|
| 235 |
+ my $tag_end = $builder->tag_start; |
|
| 236 |
+ $builder = $builder->tag_start('}');
|
|
| 237 |
+ |
|
| 238 |
+String of tag end. |
|
| 239 |
+Default to '}' |
|
| 240 |
+ |
|
| 241 |
+=head2 C<tag_syntax> |
|
| 242 |
+ |
|
| 243 |
+ my $tag_syntax = $builder->tag_syntax; |
|
| 244 |
+ $builder = $builder->tag_syntax($tag_syntax); |
|
| 245 |
+ |
|
| 246 |
+Tag syntax. |
|
| 247 |
+ |
|
| 248 |
+=head1 METHODS |
|
| 249 |
+ |
|
| 250 |
+This class is L<Object::Simple> subclass. |
|
| 251 |
+You can use all methods of L<Object::Simple> |
|
| 252 |
+ |
|
| 253 |
+=head2 C<new> |
|
| 254 |
+ |
|
| 255 |
+ my $builder = DBIx::Custom::SQLBuilder->new; |
|
| 256 |
+ my $builder = DBIx::Custom::SQLBuilder->new(%attrs); |
|
| 257 |
+ my $builder = DBIx::Custom::SQLBuilder->new(\%attrs); |
|
| 258 |
+ |
|
| 259 |
+Create a instance. |
|
| 260 |
+ |
|
| 261 |
+=head2 C<build_query> |
|
| 262 |
+ |
|
| 263 |
+ my $query = $builder->build_query($source); |
|
| 264 |
+ |
|
| 265 |
+Build L<DBIx::Custom::Query> object. |
|
| 266 |
+ |
|
| 267 |
+B<Example:> |
|
| 268 |
+ |
|
| 269 |
+Source: |
|
| 270 |
+ |
|
| 271 |
+ my $query = $builder->build_query( |
|
| 272 |
+ "select * from table where {= title} && {like author} || {<= price}")
|
|
| 273 |
+ |
|
| 274 |
+Query: |
|
| 275 |
+ |
|
| 276 |
+ $qeury->sql : "select * from table where title = ? && author like ? price <= ?;" |
|
| 277 |
+ $query->columns : ['title', 'author', 'price'] |
|
| 278 |
+ |
|
| 279 |
+=head2 C<register_tag_processor> |
|
| 280 |
+ |
|
| 281 |
+ $builder = $builder->register_tag_processor($tag_processor); |
|
| 282 |
+ |
|
| 283 |
+Register tag processor. |
|
| 284 |
+ |
|
| 285 |
+ $builder->register_tag_processor( |
|
| 286 |
+ '?' => sub {
|
|
| 287 |
+ my $args = shift; |
|
| 288 |
+ |
|
| 289 |
+ # Do something |
|
| 290 |
+ |
|
| 291 |
+ # Expanded tag and column names |
|
| 292 |
+ return ($expand, $columns); |
|
| 293 |
+ } |
|
| 294 |
+ ); |
|
| 295 |
+ |
|
| 296 |
+Tag processor receive arguments in tags |
|
| 297 |
+and must return expanded tag and column names. |
|
| 298 |
+ |
|
| 299 |
+=head1 Tags |
|
| 300 |
+ |
|
| 301 |
+ {? NAME} -> ?
|
|
| 302 |
+ {= NAME} -> NAME = ?
|
|
| 303 |
+ {<> NAME} -> NAME <> ?
|
|
| 304 |
+ |
|
| 305 |
+ {< NAME} -> NAME < ?
|
|
| 306 |
+ {> NAME} -> NAME > ?
|
|
| 307 |
+ {>= NAME} -> NAME >= ?
|
|
| 308 |
+ {<= NAME} -> NAME <= ?
|
|
| 309 |
+ |
|
| 310 |
+ {like NAME} -> NAME like ?
|
|
| 311 |
+ {in NAME COUNT} -> NAME in [?, ?, ..]
|
|
| 312 |
+ |
|
| 313 |
+ {insert NAME1 NAME2 NAME3} -> (NAME1, NAME2, NAME3) values (?, ?, ?)
|
|
| 314 |
+ {update NAME1 NAME2 NAME3} -> set NAME1 = ?, NAME2 = ?, NAME3 = ?
|
| ... | ... |
@@ -1,4 +1,4 @@ |
| 1 |
-package DBIx::Custom::SQLTemplate::TagProcessors; |
|
| 1 |
+package DBIx::Custom::QueryBuilder::TagProcessors; |
|
| 2 | 2 |
|
| 3 | 3 |
use strict; |
| 4 | 4 |
use warnings; |
| ... | ... |
@@ -117,7 +117,7 @@ sub expand_update_tag {
|
| 117 | 117 |
|
| 118 | 118 |
=head1 NAME |
| 119 | 119 |
|
| 120 |
-DBIx::Custom::SQLTemplate::TagProcessor - Tag processor |
|
| 120 |
+DBIx::Custom::SQLBuilder::TagProcessors - Tag processor |
|
| 121 | 121 |
|
| 122 | 122 |
=head1 FUNCTIONS |
| 123 | 123 |
|
| ... | ... |
@@ -1,374 +0,0 @@ |
| 1 |
-package DBIx::Custom::SQLTemplate; |
|
| 2 |
- |
|
| 3 |
-use strict; |
|
| 4 |
-use warnings; |
|
| 5 |
- |
|
| 6 |
-use base 'Object::Simple'; |
|
| 7 |
- |
|
| 8 |
-use Carp 'croak'; |
|
| 9 |
-use DBIx::Custom::Query; |
|
| 10 |
-use DBIx::Custom::SQLTemplate::TagProcessor; |
|
| 11 |
- |
|
| 12 |
-__PACKAGE__->attr('tag_processors' => sub { {} });
|
|
| 13 |
- |
|
| 14 |
-__PACKAGE__->attr(tag_start => '{');
|
|
| 15 |
-__PACKAGE__->attr(tag_end => '}'); |
|
| 16 |
- |
|
| 17 |
-__PACKAGE__->attr('tag_syntax' => <<'EOS');
|
|
| 18 |
-[tag] [expand] |
|
| 19 |
-{? name} ?
|
|
| 20 |
-{= name} name = ?
|
|
| 21 |
-{<> name} name <> ?
|
|
| 22 |
- |
|
| 23 |
-{< name} name < ?
|
|
| 24 |
-{> name} name > ?
|
|
| 25 |
-{>= name} name >= ?
|
|
| 26 |
-{<= name} name <= ?
|
|
| 27 |
- |
|
| 28 |
-{like name} name like ?
|
|
| 29 |
-{in name number} name in [?, ?, ..]
|
|
| 30 |
- |
|
| 31 |
-{insert key1 key2} (key1, key2) values (?, ?)
|
|
| 32 |
-{update key1 key2} set key1 = ?, key2 = ?
|
|
| 33 |
-EOS |
|
| 34 |
- |
|
| 35 |
-sub new {
|
|
| 36 |
- my $self = shift->SUPER::new; |
|
| 37 |
- |
|
| 38 |
- $self->register_tag_processor( |
|
| 39 |
- '?' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_placeholder_tag, |
|
| 40 |
- '=' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 41 |
- '<>' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 42 |
- '>' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 43 |
- '<' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 44 |
- '>=' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 45 |
- '<=' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 46 |
- 'like' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_basic_tag, |
|
| 47 |
- 'in' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_in_tag, |
|
| 48 |
- 'insert' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_insert_tag, |
|
| 49 |
- 'update' => \&DBIx::Custom::SQLTemplate::TagProcessors::expand_update_tag |
|
| 50 |
- ); |
|
| 51 |
- |
|
| 52 |
- return $self; |
|
| 53 |
-} |
|
| 54 |
- |
|
| 55 |
-sub register_tag_processor {
|
|
| 56 |
- my $self = shift; |
|
| 57 |
- my $tag_processors = ref $_[0] eq 'HASH' ? $_[0] : {@_};
|
|
| 58 |
- $self->tag_processors({%{$self->tag_processors}, %{$tag_processors}});
|
|
| 59 |
- return $self; |
|
| 60 |
-} |
|
| 61 |
- |
|
| 62 |
-sub create_query {
|
|
| 63 |
- my ($self, $template) = @_; |
|
| 64 |
- |
|
| 65 |
- # Parse template |
|
| 66 |
- my $tree = $self->_parse_template($template); |
|
| 67 |
- |
|
| 68 |
- # Build query |
|
| 69 |
- my $query = $self->_build_query($tree); |
|
| 70 |
- |
|
| 71 |
- return $query; |
|
| 72 |
-} |
|
| 73 |
- |
|
| 74 |
-sub _parse_template {
|
|
| 75 |
- my ($self, $template) = @_; |
|
| 76 |
- |
|
| 77 |
- if (ref $template eq 'ARRAY') {
|
|
| 78 |
- $template = $template->[1]; |
|
| 79 |
- } |
|
| 80 |
- $template ||= ''; |
|
| 81 |
- |
|
| 82 |
- my $tree = []; |
|
| 83 |
- |
|
| 84 |
- # Tags |
|
| 85 |
- my $tag_start = quotemeta $self->tag_start; |
|
| 86 |
- my $tag_end = quotemeta $self->tag_end; |
|
| 87 |
- |
|
| 88 |
- # Tokenize |
|
| 89 |
- my $state = 'text'; |
|
| 90 |
- |
|
| 91 |
- # Save original template |
|
| 92 |
- my $original_template = $template; |
|
| 93 |
- |
|
| 94 |
- # Parse template |
|
| 95 |
- while ($template =~ s/([^$tag_start]*?)$tag_start([^$tag_end].*?)$tag_end//sm) {
|
|
| 96 |
- my $text = $1; |
|
| 97 |
- my $tag = $2; |
|
| 98 |
- |
|
| 99 |
- # Parse tree |
|
| 100 |
- push @$tree, {type => 'text', tag_args => [$text]} if $text;
|
|
| 101 |
- |
|
| 102 |
- if ($tag) {
|
|
| 103 |
- # Get tag name and arguments |
|
| 104 |
- my ($tag_name, @tag_args) = split /\s+/, $tag; |
|
| 105 |
- |
|
| 106 |
- # Tag processor is exist? |
|
| 107 |
- unless ($self->tag_processors->{$tag_name}) {
|
|
| 108 |
- my $tag_syntax = $self->tag_syntax; |
|
| 109 |
- croak("Tag '{$tag}' in SQL template is not exist.\n\n" .
|
|
| 110 |
- "<SQL template tag syntax>\n" . |
|
| 111 |
- "$tag_syntax\n" . |
|
| 112 |
- "<Your SQL template>\n" . |
|
| 113 |
- "$original_template\n\n"); |
|
| 114 |
- } |
|
| 115 |
- |
|
| 116 |
- # Check tag arguments |
|
| 117 |
- foreach my $tag_arg (@tag_args) {
|
|
| 118 |
- # Cannot cantain placehosder '?' |
|
| 119 |
- croak("Tag '{t }' arguments cannot contain '?'")
|
|
| 120 |
- if $tag_arg =~ /\?/; |
|
| 121 |
- } |
|
| 122 |
- |
|
| 123 |
- # Add tag to parsing tree |
|
| 124 |
- push @$tree, {type => 'tag', tag_name => $tag_name, tag_args => [@tag_args]};
|
|
| 125 |
- } |
|
| 126 |
- } |
|
| 127 |
- |
|
| 128 |
- # Add text to parsing tree |
|
| 129 |
- push @$tree, {type => 'text', tag_args => [$template]} if $template;
|
|
| 130 |
- |
|
| 131 |
- return $tree; |
|
| 132 |
-} |
|
| 133 |
- |
|
| 134 |
-sub _build_query {
|
|
| 135 |
- my ($self, $tree) = @_; |
|
| 136 |
- |
|
| 137 |
- # SQL |
|
| 138 |
- my $sql = ''; |
|
| 139 |
- |
|
| 140 |
- # All parameter key infomation |
|
| 141 |
- my $all_columns = []; |
|
| 142 |
- |
|
| 143 |
- # Build SQL |
|
| 144 |
- foreach my $node (@$tree) {
|
|
| 145 |
- |
|
| 146 |
- # Get type, tag name, and arguments |
|
| 147 |
- my $type = $node->{type};
|
|
| 148 |
- my $tag_name = $node->{tag_name};
|
|
| 149 |
- my $tag_args = $node->{tag_args};
|
|
| 150 |
- |
|
| 151 |
- # Text |
|
| 152 |
- if ($type eq 'text') {
|
|
| 153 |
- # Join text |
|
| 154 |
- $sql .= $tag_args->[0]; |
|
| 155 |
- } |
|
| 156 |
- |
|
| 157 |
- # Tag |
|
| 158 |
- elsif ($type eq 'tag') {
|
|
| 159 |
- |
|
| 160 |
- # Get tag processor |
|
| 161 |
- my $tag_processor = $self->tag_processors->{$tag_name};
|
|
| 162 |
- |
|
| 163 |
- # Tag processor is code ref? |
|
| 164 |
- croak("Tag processor '$tag_name' must be code reference")
|
|
| 165 |
- unless ref $tag_processor eq 'CODE'; |
|
| 166 |
- |
|
| 167 |
- # Expand tag using tag processor |
|
| 168 |
- my ($expand, $columns) = $tag_processor->($tag_name, $tag_args); |
|
| 169 |
- |
|
| 170 |
- # Check tag processor return value |
|
| 171 |
- croak("Tag processor '$tag_name' must return (\$expand, \$columns)")
|
|
| 172 |
- if !defined $expand || ref $columns ne 'ARRAY'; |
|
| 173 |
- |
|
| 174 |
- # Check placeholder count |
|
| 175 |
- croak("Placeholder count in SQL created by tag processor '$tag_name' " .
|
|
| 176 |
- "must be same as key informations count") |
|
| 177 |
- unless $self->_placeholder_count($expand) eq @$columns; |
|
| 178 |
- |
|
| 179 |
- # Add key information |
|
| 180 |
- push @$all_columns, @$columns; |
|
| 181 |
- |
|
| 182 |
- # Join expand tag to SQL |
|
| 183 |
- $sql .= $expand; |
|
| 184 |
- } |
|
| 185 |
- } |
|
| 186 |
- |
|
| 187 |
- # Add semicolon |
|
| 188 |
- $sql .= ';' unless $sql =~ /;$/; |
|
| 189 |
- |
|
| 190 |
- # Query |
|
| 191 |
- my $query = DBIx::Custom::Query->new(sql => $sql, columns => $all_columns); |
|
| 192 |
- |
|
| 193 |
- return $query; |
|
| 194 |
-} |
|
| 195 |
- |
|
| 196 |
-sub _placeholder_count {
|
|
| 197 |
- my ($self, $expand) = @_; |
|
| 198 |
- $expand ||= ''; |
|
| 199 |
- |
|
| 200 |
- my $count = 0; |
|
| 201 |
- my $pos = -1; |
|
| 202 |
- while (($pos = index($expand, '?', $pos + 1)) != -1) {
|
|
| 203 |
- $count++; |
|
| 204 |
- } |
|
| 205 |
- return $count; |
|
| 206 |
-} |
|
| 207 |
- |
|
| 208 |
-1; |
|
| 209 |
- |
|
| 210 |
-=head1 NAME |
|
| 211 |
- |
|
| 212 |
-DBIx::Custom::SQLTemplate - SQL template system |
|
| 213 |
- |
|
| 214 |
-=head1 SYNOPSIS |
|
| 215 |
- |
|
| 216 |
- my $sql_tmpl = DBIx::Custom::SQLTemplate->new; |
|
| 217 |
- |
|
| 218 |
- my $tmpl = "select from table {= k1} && {<> k2} || {like k3}";
|
|
| 219 |
- my $param = {k1 => 1, k2 => 2, k3 => 3};
|
|
| 220 |
- |
|
| 221 |
- my $query = $sql_template->create_query($tmpl); |
|
| 222 |
- |
|
| 223 |
-=head1 ATTRIBUTES |
|
| 224 |
- |
|
| 225 |
-=head2 C<tag_processors> |
|
| 226 |
- |
|
| 227 |
- $sql_tmpl = $sql_tmpl->tag_processors($name1 => $tag_processor1 |
|
| 228 |
- $name2 => $tag_processor2); |
|
| 229 |
- $tag_processors = $sql_tmpl->tag_processors; |
|
| 230 |
- |
|
| 231 |
-=head2 C<tag_start> |
|
| 232 |
- |
|
| 233 |
- $sql_tmpl = $sql_tmpl->tag_start('{');
|
|
| 234 |
- $tag_start = $sql_tmpl->tag_start; |
|
| 235 |
- |
|
| 236 |
-Default is '{'
|
|
| 237 |
- |
|
| 238 |
-=head2 C<tag_end> |
|
| 239 |
- |
|
| 240 |
- $sql_tmpl = $sql_tmpl->tag_start('}');
|
|
| 241 |
- $tag_end = $sql_tmpl->tag_start; |
|
| 242 |
- |
|
| 243 |
-Default is '}' |
|
| 244 |
- |
|
| 245 |
-=head2 C<tag_syntax> |
|
| 246 |
- |
|
| 247 |
- $sql_tmpl = $sql_tmpl->tag_syntax($tag_syntax); |
|
| 248 |
- $tag_syntax = $sql_tmpl->tag_syntax; |
|
| 249 |
- |
|
| 250 |
-=head1 METHODS |
|
| 251 |
- |
|
| 252 |
-This class is L<Object::Simple> subclass. |
|
| 253 |
-You can use all methods of L<Object::Simple> |
|
| 254 |
- |
|
| 255 |
-=head2 C<new> |
|
| 256 |
- |
|
| 257 |
-=head2 C<create_query> |
|
| 258 |
- |
|
| 259 |
-Create L<DBIx::Custom::Query> object parsing SQL template |
|
| 260 |
- |
|
| 261 |
- $query = $sql_tmpl->create_query($tmpl); |
|
| 262 |
- |
|
| 263 |
- # Sample |
|
| 264 |
- $query = $sql_tmpl->create_sql( |
|
| 265 |
- "select * from table where {= title} && {like author} || {<= price}")
|
|
| 266 |
- |
|
| 267 |
- # Expanded |
|
| 268 |
- $qeury->sql : "select * from table where title = ? && author like ? price <= ?;" |
|
| 269 |
- $query->key_infos : [['title'], ['author'], ['price']] |
|
| 270 |
- |
|
| 271 |
- # Sample with table name |
|
| 272 |
- ($sql, @bind_values) = $sql_tmpl->create_sql( |
|
| 273 |
- "select * from table where {= table.title} && {like table.author}",
|
|
| 274 |
- {table => {title => 'Perl', author => '%Taro%'}}
|
|
| 275 |
- ) |
|
| 276 |
- |
|
| 277 |
- # Expanded |
|
| 278 |
- $query->sql : "select * from table where table.title = ? && table.title like ?;" |
|
| 279 |
- $query->key_infos :[ [['table.title'],['table', 'title']], |
|
| 280 |
- [['table.author'],['table', 'author']] ] |
|
| 281 |
- |
|
| 282 |
-This method create query using by L<DBIx::Custom>. |
|
| 283 |
-query has two infomation |
|
| 284 |
- |
|
| 285 |
- 1. sql : SQL |
|
| 286 |
- 2. key_infos : Parameter access key information |
|
| 287 |
- |
|
| 288 |
-=head2 C<register_tag_processor> |
|
| 289 |
- |
|
| 290 |
-Add tag processor |
|
| 291 |
- |
|
| 292 |
- $sql_tmpl = $sql_tmpl->register_tag_processor($tag_processor); |
|
| 293 |
- |
|
| 294 |
-The following is register_tag_processor sample |
|
| 295 |
- |
|
| 296 |
- $sql_tmpl->register_tag_processor( |
|
| 297 |
- '?' => sub {
|
|
| 298 |
- my ($tag_name, $tag_args) = @_; |
|
| 299 |
- |
|
| 300 |
- my $key1 = $tag_args->[0]; |
|
| 301 |
- my $key2 = $tag_args->[1]; |
|
| 302 |
- |
|
| 303 |
- my $key_infos = []; |
|
| 304 |
- |
|
| 305 |
- # Expand tag and create key informations |
|
| 306 |
- |
|
| 307 |
- # Return expand tags and key informations |
|
| 308 |
- return ($expand, $key_infos); |
|
| 309 |
- } |
|
| 310 |
- ); |
|
| 311 |
- |
|
| 312 |
-Tag processor recieve 2 argument |
|
| 313 |
- |
|
| 314 |
- 1. Tag name (?, =, <>, or etc) |
|
| 315 |
- 2. Tag arguments (arg1 and arg2 in {tag_name arg1 arg2})
|
|
| 316 |
- |
|
| 317 |
-Tag processor return 2 value |
|
| 318 |
- |
|
| 319 |
- 1. Expanded Tag (For exsample, '{= title}' is expanded to 'title = ?')
|
|
| 320 |
- 2. Key infomations |
|
| 321 |
- |
|
| 322 |
-You must be return expanded tag and key infomations. |
|
| 323 |
- |
|
| 324 |
-Key information is a little complex. so I will explan this in future. |
|
| 325 |
- |
|
| 326 |
-If you want to know more, Please see DBIx::Custom::SQLTemplate source code. |
|
| 327 |
- |
|
| 328 |
-=head2 C<clone> |
|
| 329 |
- |
|
| 330 |
-Clone DBIx::Custom::SQLTemplate object |
|
| 331 |
- |
|
| 332 |
- $clone = $sql_tmpl->clone; |
|
| 333 |
- |
|
| 334 |
-=head1 Available Tags |
|
| 335 |
- |
|
| 336 |
-Available Tags |
|
| 337 |
- |
|
| 338 |
- [tag] [expand] |
|
| 339 |
- {? name} ?
|
|
| 340 |
- {= name} name = ?
|
|
| 341 |
- {<> name} name <> ?
|
|
| 342 |
- |
|
| 343 |
- {< name} name < ?
|
|
| 344 |
- {> name} name > ?
|
|
| 345 |
- {>= name} name >= ?
|
|
| 346 |
- {<= name} name <= ?
|
|
| 347 |
- |
|
| 348 |
- {like name} name like ?
|
|
| 349 |
- {in name} name in [?, ?, ..]
|
|
| 350 |
- |
|
| 351 |
- {insert} (key1, key2, key3) values (?, ?, ?)
|
|
| 352 |
- {update} set key1 = ?, key2 = ?, key3 = ?
|
|
| 353 |
- |
|
| 354 |
- |
|
| 355 |
-The following is insert SQL sample |
|
| 356 |
- |
|
| 357 |
- $query = $sql_tmpl->create_sql( |
|
| 358 |
- "insert into table {insert key1 key2}"
|
|
| 359 |
- ); |
|
| 360 |
- |
|
| 361 |
- # Expanded |
|
| 362 |
- $query->sql : "insert into table (key1, key2) values (?, ?)" |
|
| 363 |
- |
|
| 364 |
-The following is update SQL sample |
|
| 365 |
- |
|
| 366 |
- $query = $sql_tmpl->create_sql( |
|
| 367 |
- "update table {update key1 key2} where {= key3}"
|
|
| 368 |
- ); |
|
| 369 |
- |
|
| 370 |
- # Expanded |
|
| 371 |
- $query->sql : "update table set key1 = ?, key2 = ? where key3 = ?;" |
|
| 372 |
- |
|
| 373 |
-=cut |
|
| 374 |
- |
| ... | ... |
@@ -70,7 +70,7 @@ $dbi->insert(table => 'table1', param => {key1 => 3, key2 => 4});
|
| 70 | 70 |
|
| 71 | 71 |
test 'DBIx::Custom::Result test'; |
| 72 | 72 |
$tmpl = "select key1, key2 from table1"; |
| 73 |
-$query = $dbi->create_query($tmpl); |
|
| 73 |
+$query = $dbi->build_query($tmpl); |
|
| 74 | 74 |
$result = $dbi->execute($query); |
| 75 | 75 |
|
| 76 | 76 |
@rows = (); |
| ... | ... |
@@ -98,7 +98,7 @@ test 'Insert query return value'; |
| 98 | 98 |
$dbi->execute($DROP_TABLE->{0});
|
| 99 | 99 |
$dbi->execute($CREATE_TABLE->{0});
|
| 100 | 100 |
$tmpl = "insert into table1 {insert key1 key2}";
|
| 101 |
-$query = $dbi->create_query($tmpl); |
|
| 101 |
+$query = $dbi->build_query($tmpl); |
|
| 102 | 102 |
$ret_val = $dbi->execute($query, param => {key1 => 1, key2 => 2});
|
| 103 | 103 |
ok($ret_val, $test); |
| 104 | 104 |
|
| ... | ... |
@@ -119,7 +119,7 @@ $dbi->register_filter(twice => sub { $_[0] * 2},
|
| 119 | 119 |
three_times => sub { $_[0] * 3});
|
| 120 | 120 |
|
| 121 | 121 |
$insert_tmpl = "insert into table1 {insert key1 key2};";
|
| 122 |
-$insert_query = $dbi->create_query($insert_tmpl); |
|
| 122 |
+$insert_query = $dbi->build_query($insert_tmpl); |
|
| 123 | 123 |
$insert_query->filter({key1 => 'twice'});
|
| 124 | 124 |
$dbi->execute($insert_query, param => {key1 => 1, key2 => 2});
|
| 125 | 125 |
$result = $dbi->execute($SELECT_TMPLS->{0});
|
| ... | ... |
@@ -130,10 +130,10 @@ $dbi->execute($DROP_TABLE->{0});
|
| 130 | 130 |
test 'Filter in'; |
| 131 | 131 |
$dbi->execute($CREATE_TABLE->{0});
|
| 132 | 132 |
$insert_tmpl = "insert into table1 {insert key1 key2};";
|
| 133 |
-$insert_query = $dbi->create_query($insert_tmpl); |
|
| 133 |
+$insert_query = $dbi->build_query($insert_tmpl); |
|
| 134 | 134 |
$dbi->execute($insert_query, param => {key1 => 2, key2 => 4});
|
| 135 | 135 |
$select_tmpl = "select * from table1 where {in table1.key1 2} and {in table1.key2 2}";
|
| 136 |
-$select_query = $dbi->create_query($select_tmpl); |
|
| 136 |
+$select_query = $dbi->build_query($select_tmpl); |
|
| 137 | 137 |
$select_query->filter({'table1.key1' => 'twice'});
|
| 138 | 138 |
$result = $dbi->execute($select_query, param => {'table1.key1' => [1,5], 'table1.key2' => [2,4]});
|
| 139 | 139 |
$rows = $result->fetch_hash_all; |
| ... | ... |
@@ -146,13 +146,13 @@ $dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3, key4
|
| 146 | 146 |
$dbi->insert(table => 'table1', param => {key1 => 6, key2 => 7, key3 => 8, key4 => 9, key5 => 10});
|
| 147 | 147 |
|
| 148 | 148 |
$tmpl = "select * from table1 where {= key1} and {<> key2} and {< key3} and {> key4} and {>= key5};";
|
| 149 |
-$query = $dbi->create_query($tmpl); |
|
| 149 |
+$query = $dbi->build_query($tmpl); |
|
| 150 | 150 |
$result = $dbi->execute($query, param => {key1 => 1, key2 => 3, key3 => 4, key4 => 3, key5 => 5});
|
| 151 | 151 |
$rows = $result->fetch_hash_all; |
| 152 | 152 |
is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$test : basic tag1");
|
| 153 | 153 |
|
| 154 | 154 |
$tmpl = "select * from table1 where {<= key1} and {like key2};";
|
| 155 |
-$query = $dbi->create_query($tmpl); |
|
| 155 |
+$query = $dbi->build_query($tmpl); |
|
| 156 | 156 |
$result = $dbi->execute($query, param => {key1 => 1, key2 => '%2%'});
|
| 157 | 157 |
$rows = $result->fetch_hash_all; |
| 158 | 158 |
is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$test : basic tag2");
|
| ... | ... |
@@ -164,7 +164,7 @@ $dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2, key3 => 3, key4
|
| 164 | 164 |
$dbi->insert(table => 'table1', param => {key1 => 6, key2 => 7, key3 => 8, key4 => 9, key5 => 10});
|
| 165 | 165 |
|
| 166 | 166 |
$tmpl = "select * from table1 where {in key1 2};";
|
| 167 |
-$query = $dbi->create_query($tmpl); |
|
| 167 |
+$query = $dbi->build_query($tmpl); |
|
| 168 | 168 |
$result = $dbi->execute($query, param => {key1 => [9, 1]});
|
| 169 | 169 |
$rows = $result->fetch_hash_all; |
| 170 | 170 |
is_deeply($rows, [{key1 => 1, key2 => 2, key3 => 3, key4 => 4, key5 => 5}], "$test : basic");
|
| ... | ... |
@@ -197,8 +197,8 @@ eval {DBIx::Custom->connect(data_source => 'dbi:SQLit')};
|
| 197 | 197 |
ok($@, "$test : connect error"); |
| 198 | 198 |
|
| 199 | 199 |
$dbi = DBIx::Custom->connect($NEW_ARGS->{0});
|
| 200 |
-eval{$dbi->create_query("{p }")};
|
|
| 201 |
-ok($@, "$test : create_query invalid SQL template"); |
|
| 200 |
+eval{$dbi->build_query("{p }")};
|
|
| 201 |
+ok($@, "$test : build_query invalid SQL template"); |
|
| 202 | 202 |
|
| 203 | 203 |
test 'insert'; |
| 204 | 204 |
$dbi = DBIx::Custom->connect($NEW_ARGS->{0});
|
| ... | ... |
@@ -214,12 +214,12 @@ $dbi->register_filter( |
| 214 | 214 |
twice => sub { $_[0] * 2 },
|
| 215 | 215 |
three_times => sub { $_[0] * 3 }
|
| 216 | 216 |
); |
| 217 |
-$dbi->default_query_filter('twice');
|
|
| 217 |
+$dbi->default_bind_filter('twice');
|
|
| 218 | 218 |
$dbi->insert(table => 'table1', param => {key1 => 1, key2 => 2}, filter => {key1 => 'three_times'});
|
| 219 | 219 |
$result = $dbi->execute($SELECT_TMPLS->{0});
|
| 220 | 220 |
$rows = $result->fetch_hash_all; |
| 221 | 221 |
is_deeply($rows, [{key1 => 3, key2 => 4}], "$test : filter");
|
| 222 |
-$dbi->default_query_filter(undef); |
|
| 222 |
+$dbi->default_bind_filter(undef); |
|
| 223 | 223 |
|
| 224 | 224 |
$dbi->execute($DROP_TABLE->{0});
|
| 225 | 225 |
$dbi->execute($CREATE_TABLE->{0});
|
| ... | ... |
@@ -414,7 +414,7 @@ test 'cache'; |
| 414 | 414 |
$dbi = DBIx::Custom->connect($NEW_ARGS->{0});
|
| 415 | 415 |
$dbi->execute($CREATE_TABLE->{0});
|
| 416 | 416 |
$tmpl = 'select * from table1 where {= key1} and {= key2};';
|
| 417 |
-$dbi->create_query($tmpl); |
|
| 417 |
+$dbi->build_query($tmpl); |
|
| 418 | 418 |
is_deeply($dbi->{_cached}->{$tmpl},
|
| 419 | 419 |
{sql => "select * from table1 where key1 = ? and key2 = ?;", columns => ['key1', 'key2']}, "$test : cache");
|
| 420 | 420 |
|
| ... | ... |
@@ -31,12 +31,12 @@ $dbi = DBIx::Custom->new( |
| 31 | 31 |
default_bind_filter => 'f', |
| 32 | 32 |
default_fetch_filter => 'g', |
| 33 | 33 |
result_class => 'g', |
| 34 |
- sql_template => $SQL_TMPL->{0},
|
|
| 34 |
+ sql_builder_class => $SQL_TMPL->{0},
|
|
| 35 | 35 |
); |
| 36 | 36 |
is_deeply($dbi,{user => 'a', database => 'a', password => 'b', data_source => 'c',
|
| 37 | 37 |
filters => {f => 3}, default_bind_filter => 'f',
|
| 38 | 38 |
default_fetch_filter => 'g', result_class => 'g', |
| 39 |
- sql_template => $SQL_TMPL->{0}}, $test);
|
|
| 39 |
+ sql_builder_class => $SQL_TMPL->{0}}, $test);
|
|
| 40 | 40 |
isa_ok($dbi, 'DBIx::Custom'); |
| 41 | 41 |
|
| 42 | 42 |
|