DBIx-Custom / lib / DBIx / Custom / QueryBuilder.pm /
Newer Older
301 lines | 8.604kb
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

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

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

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

            
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
75
    # Create query
add table tag
Yuki Kimoto authored on 2011-02-09
76
    my $query = DBIx::Custom::Query->new(
77
        sql => $sql,
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
78
        columns => $columns
add table tag
Yuki Kimoto authored on 2011-02-09
79
    );
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
80
    
81
    return $query;
82
}
- DBIx::Custom::QueryBuilder...
Yuki Kimoto authored on 2011-11-04
83

            
84
# DEPRECATED
85
has 'dbi';
86

            
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
87
# DEPRECATED!
cleanup
Yuki Kimoto authored on 2011-06-13
88
has tags => sub { {} };
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
89

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

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

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

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

            
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
291
1;
292

            
293
=head1 NAME
294

            
- DBIx::Custom::QueryBuilder...
Yuki Kimoto authored on 2011-11-04
295
DBIx::Custom::QueryBuilder - DEPRECATED!
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
296

            
- DBIx::Custom::QueryBuilder...
Yuki Kimoto authored on 2011-11-04
297
=head1 DESCRIPTION
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
298

            
- DBIx::Custom::QueryBuilder...
Yuki Kimoto authored on 2011-11-04
299
This module functionality will be moved to DBIx::Custom
update document
yuki-kimoto authored on 2010-08-07
300

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