DBIx-Custom / lib / DBIx / Custom / QueryBuilder.pm /
Newer Older
276 lines | 6.668kb
cleanup
Yuki Kimoto authored on 2011-11-18
1
# DEPRECATED!
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
2
package DBIx::Custom::QueryBuilder;
3

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

            
6
use Carp 'croak';
7
use DBIx::Custom::Query;
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
8
use DBIx::Custom::Util qw/_subname _deprecate/;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
9

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

            
cleanup
Yuki Kimoto authored on 2011-11-18
14
# DEPRECATED!
cleanup
yuki-kimoto authored on 2010-10-17
15
sub build_query {
cleanup
Yuki Kimoto authored on 2012-01-20
16
  my ($self, $sql) = @_;
cleanup
Yuki Kimoto authored on 2011-11-18
17

            
cleanup
Yuki Kimoto authored on 2012-01-20
18
  my $query = $self->_parse_tag($sql);
19
  my $tag_count = delete $query->{tag_count};
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
20
  _deprecate('0.24', qq/Tag system such as {? name} is DEPRECATED! / .
21
      qq/use parameter system such as :name instead/)
cleanup
Yuki Kimoto authored on 2012-01-20
22
    if $tag_count;
23
  my $query2 = $self->_parse_parameter($query->sql);
24
  $query->sql($query2->sql);
25
  for (my $i =0; $i < @{$query->columns}; $i++) {
26
    my $column = $query->columns->[$i];
27
    if ($column eq 'RESERVED_PARAMETER') {
28
      my $column2 = shift @{$query2->columns};
29
      croak ":name syntax is wrong"
30
        unless defined $column2;
31
      $query->columns->[$i] = $column2;
micro optimization
Yuki Kimoto authored on 2011-10-24
32
    }
cleanup
Yuki Kimoto authored on 2012-01-20
33
  }
34
  return $query;
cleanup
yuki-kimoto authored on 2010-10-17
35
}
36

            
cleanup
Yuki Kimoto authored on 2011-10-24
37
# DEPRECATED!
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
38
sub _parse_parameter {
cleanup
Yuki Kimoto authored on 2012-01-20
39
  my ($self, $source) = @_;
40
  
41
  # Get and replace parameters
42
  my $sql = $source || '';
43
  my $columns = [];
44
  my $c = $self->dbi->safety_character;
45
  # Parameter regex
46
  $sql =~ s/([^:]):(\d+):([^:])/$1\\:$2\\:$3/g;
47
  my $re = qr/(^|.*?[^\\]):([$c\.]+)(?:\{(.*?)\})?(.*)/s;
48
  while ($sql =~ /$re/g) {
49
    push @$columns, $2;
50
    $sql = defined $3 ? "$1$2 $3 ?$4" : "$1?$4";
51
  }
52
  $sql =~ s/\\:/:/g;
cleanup
yuki-kimoto authored on 2010-10-17
53

            
cleanup
Yuki Kimoto authored on 2012-01-20
54
  # Create query
55
  my $query = DBIx::Custom::Query->new(
56
    sql => $sql,
57
    columns => $columns
58
  );
59
  
60
  return $query;
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
61
}
- DBIx::Custom::QueryBuilder...
Yuki Kimoto authored on 2011-11-04
62

            
63
# DEPRECATED
64
has 'dbi';
65

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

            
69
# DEPRECATED!
70
sub register_tag {
cleanup
Yuki Kimoto authored on 2012-01-20
71
  my $self = shift;
72
  
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
73
  _deprecate('0.24', "register_tag is DEPRECATED!");
cleanup
Yuki Kimoto authored on 2012-01-20
74
  
75
  # Merge tag
76
  my $tags = ref $_[0] eq 'HASH' ? $_[0] : {@_};
77
  $self->tags({%{$self->tags}, %$tags});
78
  
79
  return $self;
- update_param_tag is DEPREC...
Yuki Kimoto authored on 2011-06-07
80
}
81

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

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

            
cleanup
Yuki Kimoto authored on 2011-01-25
260
# DEPRECATED!
renamed DBIx::Custom::TagPro...
Yuki Kimoto authored on 2011-01-24
261
sub register_tag_processor {
cleanup
Yuki Kimoto authored on 2012-01-20
262
  my $self = shift;
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
263
  _deprecate('0.24', "register_tag_processor is DEPRECATED!");
cleanup
Yuki Kimoto authored on 2012-01-20
264
  # Merge tag
265
  my $tag_processors = ref $_[0] eq 'HASH' ? $_[0] : {@_};
266
  $self->tag_processors({%{$self->tag_processors}, %{$tag_processors}});
267
  return $self;
renamed DBIx::Custom::TagPro...
Yuki Kimoto authored on 2011-01-24
268
}
269

            
renamed default_query_filter...
yuki-kimoto authored on 2010-08-03
270
1;
271

            
272
=head1 NAME
273

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

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