DBIx-Custom / lib / DBIx / Custom / QueryBuilder.pm /
Newer Older
311 lines | 8.594kb
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 {
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
16
    my ($self, $source) = @_;
cleanup
yuki-kimoto authored on 2010-10-17
17
    
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
18
    my $query;
19
    
20
    # Parse tag. tag is DEPRECATED!
removed undocumented DBIx::C...
Yuki Kimoto authored on 2011-08-02
21
    if ($self->dbi->tag_parse && $source =~ /(\s|^)\{/) {
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
22
        $query = $self->_parse_tag($source);
23
        my $tag_count = delete $query->{tag_count};
fixed DEPRECATED message bug
Yuki Kimoto authored on 2011-06-10
24
        warn qq/Tag system such as {? name} is DEPRECATED! / .
25
             qq/use parameter system such as :name instead/
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
26
          if $tag_count;
27
        my $query2 = $self->_parse_parameter($query->sql);
28
        $query->sql($query2->sql);
29
        for (my $i =0; $i < @{$query->columns}; $i++) {
30
            my $column = $query->columns->[$i];
31
            if ($column eq 'RESERVED_PARAMETER') {
32
                my $column2 = shift @{$query2->columns};
33
                croak ":name syntax is wrong"
34
                  unless defined $column2;
35
                $query->columns->[$i] = $column2;
36
            }
37
        }
38
    }
cleanup
yuki-kimoto authored on 2010-10-17
39
    
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
40
    # Parse parameter
added tag_parse attribute
Yuki Kimoto authored on 2011-06-28
41
    else { $query = $self->_parse_parameter($source) }
cleanup
yuki-kimoto authored on 2010-10-17
42
    
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
43
    my $sql = $query->sql;
44
    $query->sql($sql);
45
        
cleanup
yuki-kimoto authored on 2010-10-17
46
    return $query;
47
}
48

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

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

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

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

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

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

            
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
278
1;
279

            
280
=head1 NAME
281

            
282
DBIx::Custom::QueryBuilder - Query builder
283

            
284
=head1 SYNOPSIS
285
    
286
    my $builder = DBIx::Custom::QueryBuilder->new;
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
287
    my $query = $builder->build_query(
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
288
        "select from table title = :title and author = :author"
remove DBIx::Custom::QueryBu...
yuki-kimoto authored on 2010-08-05
289
    );
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
290

            
cleanup
Yuki Kimoto authored on 2011-08-02
291
=head1 ATTRIBUTES
292

            
293
=head2 C<dbi>
294

            
295
    my $dbi = $builder->dbi;
296
    $builder = $builder->dbi($dbi);
297

            
298
L<DBIx::Custom> object.
299

            
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
300
=head1 METHODS
301

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

            
305
=head2 C<build_query>
306
    
307
    my $query = $builder->build_query($source);
308

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

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