DBIx-Custom / lib / DBIx / Custom / QueryBuilder.pm /
Newer Older
317 lines | 8.91kb
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
1
package DBIx::Custom::QueryBuilder;
2

            
updatedd pod
Yuki Kimoto authored on 2011-06-12
3
use Object::Simple -base;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
4

            
5
use Carp 'croak';
6
use DBIx::Custom::Query;
cleanup
Yuki Kimoto authored on 2011-04-25
7
use DBIx::Custom::Util '_subname';
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
8

            
fixed Carp trast relationshi...
yuki-kimoto authored on 2010-08-12
9
# Carp trust relationship
10
push @DBIx::Custom::CARP_NOT, __PACKAGE__;
updated document
Yuki Kimoto authored on 2011-01-20
11
push @DBIx::Custom::Where::CARP_NOT, __PACKAGE__;
12

            
removed undocumented DBIx::C...
Yuki Kimoto authored on 2011-08-02
13
has 'dbi';
14

            
cleanup
yuki-kimoto authored on 2010-10-17
15
sub build_query {
micro optimization
Yuki Kimoto authored on 2011-10-24
16
    my ($self, $sql) = @_;
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
17
    
18
    # Parse tag. tag is DEPRECATED!
micro optimization
Yuki Kimoto authored on 2011-10-24
19
    if ($sql =~ /(\s|^)\{/ && $self->dbi->tag_parse) {
20
        my $query = $self->_parse_tag($sql);
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
21
        my $tag_count = delete $query->{tag_count};
fixed DEPRECATED message bug
Yuki Kimoto authored on 2011-06-10
22
        warn qq/Tag system such as {? name} is DEPRECATED! / .
23
             qq/use parameter system such as :name instead/
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
24
          if $tag_count;
25
        my $query2 = $self->_parse_parameter($query->sql);
26
        $query->sql($query2->sql);
27
        for (my $i =0; $i < @{$query->columns}; $i++) {
28
            my $column = $query->columns->[$i];
29
            if ($column eq 'RESERVED_PARAMETER') {
30
                my $column2 = shift @{$query2->columns};
31
                croak ":name syntax is wrong"
32
                  unless defined $column2;
33
                $query->columns->[$i] = $column2;
34
            }
35
        }
micro optimization
Yuki Kimoto authored on 2011-10-24
36
        return $query;
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
37
    }
cleanup
yuki-kimoto authored on 2010-10-17
38
    
micro optimization
Yuki Kimoto authored on 2011-10-24
39
    $sql ||= '';
40
    my $columns = [];
41
    my $c = ($self->{dbi} || {})->{safety_character}
42
      || $self->dbi->safety_character;
43
    # Parameter regex
44
    $sql =~ s/([0-9]):/$1\\:/g;
45
    while ($sql =~ /(^|.*?[^\\]):([$c\.]+)(?:\{(.*?)\})?(.*)/sg) {
46
        push @$columns, $2;
47
        $sql = defined $3 ? "$1$2 $3 ?$4" : "$1?$4";
48
    }
49
    $sql =~ s/\\:/:/g if index($sql, "\\:") != -1;
50

            
51
    # Create query
52
    bless {sql => $sql, columns => $columns}, 'DBIx::Custom::Query';
cleanup
yuki-kimoto authored on 2010-10-17
53
}
54

            
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
55
sub _parse_parameter {
56
    my ($self, $source) = @_;
fixed named placeholder bug ...
Yuki Kimoto authored on 2011-08-01
57
    
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
58
    # Get and replace parameters
59
    my $sql = $source || '';
60
    my $columns = [];
removed undocumented DBIx::C...
Yuki Kimoto authored on 2011-08-02
61
    my $c = $self->dbi->safety_character;
cleanup
Yuki Kimoto authored on 2011-07-29
62
    # Parameter regex
fixed named placeholder bug ...
Yuki Kimoto authored on 2011-08-01
63
    $sql =~ s/([^:]):(\d+):([^:])/$1\\:$2\\:$3/g;
64
    my $re = qr/(^|.*?[^\\]):([$c\.]+)(?:\{(.*?)\})?(.*)/s;
cleanup
Yuki Kimoto authored on 2011-07-29
65
    while ($sql =~ /$re/g) {
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
66
        push @$columns, $2;
added EXPERIMENTAL parameter...
Yuki Kimoto authored on 2011-07-29
67
        $sql = defined $3 ? "$1$2 $3 ?$4" : "$1?$4";
cleanup
yuki-kimoto authored on 2010-10-17
68
    }
fixed named placeholder bug ...
Yuki Kimoto authored on 2011-08-01
69
    $sql =~ s/\\:/:/g;
cleanup
yuki-kimoto authored on 2010-10-17
70

            
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
71
    # Create query
add table tag
Yuki Kimoto authored on 2011-02-09
72
    my $query = DBIx::Custom::Query->new(
73
        sql => $sql,
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
74
        columns => $columns
add table tag
Yuki Kimoto authored on 2011-02-09
75
    );
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
76
    
77
    return $query;
78
}
fixed named placeholder bug ...
Yuki Kimoto authored on 2011-08-01
79
    
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
80
# DEPRECATED!
cleanup
Yuki Kimoto authored on 2011-06-13
81
has tags => sub { {} };
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
82

            
83
# DEPRECATED!
84
sub register_tag {
85
    my $self = shift;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
86
    
added warnings
Yuki Kimoto authored on 2011-06-07
87
    warn "register_tag is DEPRECATED!";
88
    
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
89
    # Merge tag
90
    my $tags = ref $_[0] eq 'HASH' ? $_[0] : {@_};
91
    $self->tags({%{$self->tags}, %$tags});
92
    
93
    return $self;
94
}
95

            
96
# DEPRECATED!
97
sub _parse_tag {
98
    my ($self, $source) = @_;
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
99
    # Source
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
100
    $source ||= '';
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
101
    # Tree
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
102
    my @tree;
103
    # Value
104
    my $value = '';
105
    # State
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
106
    my $state = 'text';
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
107
    # Before charactor
108
    my $before = '';
109
    # Position
fixed DBIx::Custom::QueryBui...
yuki-kimoto authored on 2010-08-15
110
    my $pos = 0;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
111
    # Parse
added tests
yuki-kimoto authored on 2010-08-12
112
    my $original = $source;
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
113
    my $tag_count = 0;
fixed DBIx::Custom::QueryBui...
yuki-kimoto authored on 2010-08-15
114
    while (defined(my $c = substr($source, $pos, 1))) {
115
        # Last
116
        last unless length $c;
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
117
        # Parameter
118
        if ($c eq ':' && (substr($source, $pos + 1, 1) || '') =~ /\w/) {
119
            push @tree, {type => 'param'};;
120
        }
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
121
        # State is text
122
        if ($state eq 'text') {
123
            # Tag start charactor
124
            if ($c eq '{') {
125
                # Escaped charactor
126
                if ($before eq "\\") {
127
                    substr($value, -1, 1, '');
128
                    $value .= $c;
129
                }
130
                # Tag start
131
                else {
132
                    # Change state
133
                    $state = 'tag';
134
                    # Add text
135
                    push @tree, {type => 'text', value => $value}
136
                      if $value;
137
                    # Clear
138
                    $value = '';
139
                }
140
            }
141
            # Tag end charactor
142
            elsif ($c eq '}') {
143
                # Escaped charactor
144
                if ($before eq "\\") {
145
                    substr($value, -1, 1, '');
146
                    $value .= $c;
147
                }
148
                # Unexpected
149
                else {
improved error messages
Yuki Kimoto authored on 2011-04-18
150
                    croak qq{Parsing error. unexpected "\}". }
cleanup
Yuki Kimoto authored on 2011-04-25
151
                        . qq{pos $pos of "$original" } . _subname
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
152
                }
153
            }
154
            # Normal charactor
155
            else { $value .= $c }
156
        }
157
        # State is tags
added tests
yuki-kimoto authored on 2010-08-12
158
        else {
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
159
            # Tag start charactor
160
            if ($c eq '{') {
161
                # Escaped charactor
162
                if ($before eq "\\") {
163
                    substr($value, -1, 1, '');
164
                    $value .= $c;
165
                }
166
                # Unexpected
167
                else {
improved error messages
Yuki Kimoto authored on 2011-04-18
168
                    croak qq{Parsing error. unexpected "\{". }
cleanup
Yuki Kimoto authored on 2011-04-25
169
                        . qq{pos $pos of "$original" } . _subname
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
170
                }
171
            }
172
            # Tag end charactor
173
            elsif ($c eq '}') {
174
                # Escaped charactor
175
                if ($before eq "\\") {
176
                    substr($value, -1, 1, '');
177
                    $value .= $c;
178
                }
179
                # Tag end
180
                else {
181
                    # Change state
182
                    $state = 'text';
183
                    # Add tag
184
                    my ($tag_name, @tag_args) = split /\s+/, $value;
185
                    push @tree, {type => 'tag', tag_name => $tag_name, 
186
                                 tag_args => \@tag_args};
187
                    # Clear
188
                    $value = '';
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
189
                    # Countup
190
                    $tag_count++;
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
191
                }
192
            }
193
            # Normal charactor
194
            else { $value .= $c }
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
195
        }
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
196
        # Save before charactor
197
        $before = $c;
198
        # increment position
199
        $pos++;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
200
    }
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
201
    # Tag not finished
cleanup
Yuki Kimoto authored on 2011-04-25
202
    croak qq{Tag not finished. "$original" } . _subname
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
203
      if $state eq 'tag';
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
204
    # Not contains tag
205
    return DBIx::Custom::Query->new(sql => $source, tag_count => $tag_count)
206
      if $tag_count == 0;
removed DBIx::Custom::Query ...
yuki-kimoto authored on 2010-08-12
207
    # Add rest text
208
    push @tree, {type => 'text', value => $value}
209
      if $value;
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
210
    # SQL
211
    my $sql = '';
212
    # All Columns
213
    my $all_columns = [];
214
    # Tables
215
    my $tables = [];
216
    # Build SQL 
cleanup
Yuki Kimoto authored on 2011-10-21
217
    for my $node (@tree) {
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
218
        # Text
219
        if ($node->{type} eq 'text') { $sql .= $node->{value} }
220
        # Parameter
221
        elsif ($node->{type} eq 'param') {
222
            push @$all_columns, 'RESERVED_PARAMETER';
223
        }
224
        # Tag
225
        else {
226
            # Tag name
227
            my $tag_name = $node->{tag_name};
228
            # Tag arguments
229
            my $tag_args = $node->{tag_args};
230
            # Table
231
            if ($tag_name eq 'table') {
232
                my $table = $tag_args->[0];
233
                push @$tables, $table;
234
                $sql .= $table;
235
                next;
236
            }
237
            # Get tag
cleanup
Yuki Kimoto authored on 2011-08-13
238
            $self->dbi->{_tags} ||= {};
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
239
            my $tag = $self->tag_processors->{$tag_name}
cleanup
Yuki Kimoto authored on 2011-08-13
240
                             || $self->dbi->{_tags}->{$tag_name};
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
241
            # Tag is not registered
242
            croak qq{Tag "$tag_name" is not registered } . _subname
243
              unless $tag;
244
            # Tag not sub reference
245
            croak qq{Tag "$tag_name" must be sub reference } . _subname
246
              unless ref $tag eq 'CODE';
247
            # Execute tag
248
            my $r = $tag->(@$tag_args);
249
            # Check tag return value
250
            croak qq{Tag "$tag_name" must return [STRING, ARRAY_REFERENCE] }
251
                . _subname
252
              unless ref $r eq 'ARRAY' && defined $r->[0] && ref $r->[1] eq 'ARRAY';
253
            # Part of SQL statement and colum names
254
            my ($part, $columns) = @$r;
255
            # Add columns
256
            push @$all_columns, @$columns;
257
            # Join part tag to SQL
258
            $sql .= $part;
259
        }
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
260
    }
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
261
    # Query
262
    my $query = DBIx::Custom::Query->new(
263
        sql => $sql,
264
        columns => $all_columns,
265
        tables => $tables,
266
        tag_count => $tag_count
267
    );
268
    return $query;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
269
}
270

            
cleanup
Yuki Kimoto authored on 2011-01-25
271
# DEPRECATED!
cleanup
Yuki Kimoto authored on 2011-06-13
272
has tag_processors => sub { {} };
renamed DBIx::Custom::TagPro...
Yuki Kimoto authored on 2011-01-24
273

            
cleanup
Yuki Kimoto authored on 2011-01-25
274
# DEPRECATED!
renamed DBIx::Custom::TagPro...
Yuki Kimoto authored on 2011-01-24
275
sub register_tag_processor {
276
    my $self = shift;
- added EXPERIMENTAL order m...
Yuki Kimoto authored on 2011-06-28
277
    warn "register_tag_processor is DEPRECATED!";
cleanup
Yuki Kimoto authored on 2011-01-25
278
    # Merge tag
renamed DBIx::Custom::TagPro...
Yuki Kimoto authored on 2011-01-24
279
    my $tag_processors = ref $_[0] eq 'HASH' ? $_[0] : {@_};
280
    $self->tag_processors({%{$self->tag_processors}, %{$tag_processors}});
281
    return $self;
282
}
283

            
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
284
1;
285

            
286
=head1 NAME
287

            
288
DBIx::Custom::QueryBuilder - Query builder
289

            
290
=head1 SYNOPSIS
291
    
292
    my $builder = DBIx::Custom::QueryBuilder->new;
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
293
    my $query = $builder->build_query(
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
294
        "select from table title = :title and author = :author"
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
295
    );
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
296

            
cleanup
Yuki Kimoto authored on 2011-08-02
297
=head1 ATTRIBUTES
298

            
299
=head2 C<dbi>
300

            
301
    my $dbi = $builder->dbi;
302
    $builder = $builder->dbi($dbi);
303

            
304
L<DBIx::Custom> object.
305

            
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
306
=head1 METHODS
307

            
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
308
L<DBIx::Custom::QueryBuilder> inherits all methods from L<Object::Simple>
309
and implements the following new ones.
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
310

            
311
=head2 C<build_query>
312
    
313
    my $query = $builder->build_query($source);
314

            
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
315
Create a new L<DBIx::Custom::Query> object from SQL source.
update document
yuki-kimoto authored on 2010-08-07
316

            
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
317
=cut