sql-maker 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,6 @@
1
1
  # reference: ActiveRecord::ConnectionAdapter::Quoting
2
2
  require 'yaml'
3
+ require 'bigdecimal'
3
4
 
4
5
  module SQL::Maker::Quoting
5
6
  # Quotes the value rather than column name to help prevent
@@ -302,7 +302,7 @@ class SQL::Maker::Select
302
302
  col, val = parse_args(*args)
303
303
  col = col.to_s
304
304
  if orig = self.select_map_reverse[col]
305
- col = orig
305
+ col = orig.respond_to?(:as_sql) ? orig.as_sql : orig
306
306
  end
307
307
 
308
308
  self.having ||= self.new_condition()
@@ -332,214 +332,3 @@ class SQL::Maker::Select
332
332
  return quoted
333
333
  end
334
334
  end
335
-
336
- __END__
337
-
338
- =head1 NAME
339
-
340
- SQL::Maker::Select - dynamic SQL generator
341
-
342
- =head1 SYNOPSIS
343
-
344
- sql = SQL::Maker::Select.new
345
- .add_select('foo')
346
- .add_select('bar')
347
- .add_select('baz')
348
- .add_from('table_name' => 't')
349
- .as_sql
350
- # => "SELECT foo, bar, baz FROM table_name t"
351
-
352
- =head1 DESCRIPTION
353
-
354
- =head1 METHODS
355
-
356
- =over 4
357
-
358
- =item C<< sql = stmt.as_sql(); >>
359
-
360
- Render the SQL string.
361
-
362
- =item C<< @bind = stmt.bind(); >>
363
-
364
- Get the bind variables.
365
-
366
- =item C<< stmt.add_select('*') >>
367
-
368
- =item C<< stmt.add_select(:col => alias) >>
369
-
370
- =item C<< stmt.add_select(\'COUNT(*)' => 'cnt') >>
371
-
372
- Add a new select term. It's automatically quoted.
373
-
374
- =item C<< stmt.add_from(table :Str | select :SQL::Maker::Select) : SQL::Maker::Select >>
375
-
376
- Add a new FROM clause. You can specify the table name or an instance of L<SQL::Maker::Select> for a sub-query.
377
-
378
- I<Return:> stmt itself.
379
-
380
- =item C<< stmt.add_join(:user => {:type => 'inner', :table => 'config', :condition => 'user.user_id = config.user_id'}); >>
381
-
382
- =item C<< stmt.add_join(:user => {:type => 'inner', :table => 'config', :condition => {'user.user_id' => 'config.user_id'}); >>
383
-
384
- =item C<< stmt.add_join(:user => {:type => 'inner', :table => 'config', :condition => ['user_id']}); >>
385
-
386
- Add a new JOIN clause. If you pass an arrayref for 'condition' then it uses 'USING'. If 'type' is omitted
387
- it falls back to plain JOIN.
388
-
389
- stmt = SQL::Maker::Select.new
390
- stmt.add_join(
391
- :user => {
392
- :type => 'inner',
393
- :table => 'config',
394
- :condition => 'user.user_id = config.user_id',
395
- }
396
- )
397
- stmt.as_sql
398
- # => 'FROM user INNER JOIN config ON user.user_id = config.user_id'
399
-
400
- stmt = SQL::Maker::Select.new(:quote_char => '`', :name_sep => '.')
401
- stmt.add_join(
402
- :user => {
403
- :type => 'inner',
404
- :table => 'config',
405
- :condition => {'user.user_id' => 'config.user_id'},
406
- }
407
- )
408
- stmt.as_sql
409
- # => 'FROM `user` INNER JOIN `config` ON `user`.`user_id` = `config`.`user_id`'
410
-
411
- stmt = SQL::Maker::Select.new
412
- stmt.add_select('name')
413
- stmt.add_join(
414
- :user => {
415
- :type => 'inner',
416
- :table => 'config',
417
- :condition => ['user_id'],
418
- }
419
- )
420
- stmt.as_sql
421
- # => 'SELECT name FROM user INNER JOIN config USING (user_id)'
422
-
423
- subquery = SQL::Maker::Select.new
424
- subquery.add_select('*')
425
- subquery.add_from( 'foo' )
426
- subquery.add_where( 'hoge' => 'fuga' )
427
- stmt = SQL::Maker::Select.new
428
- stmt.add_join(
429
- [ subquery, 'bar' ] => {
430
- :type => 'inner',
431
- :table => 'baz',
432
- :alias => 'b1',
433
- :condition => 'bar.baz_id = b1.baz_id'
434
- },
435
- )
436
- stmt.as_sql
437
- # => "FROM (SELECT * FROM foo WHERE (hoge = ?)) bar INNER JOIN baz b1 ON bar.baz_id = b1.baz_id"
438
-
439
- =item C<< stmt.add_index_hint(:foo => {:type => 'USE', :list => ['index_hint']}); >>
440
-
441
- =item C<< stmt.add_index_hint(:foo => 'index_hint'); >>
442
-
443
- =item C<< stmt.add_index_hint(:foo => ['index_hint']); >>
444
-
445
- stmt = SQL::Maker::Select.new
446
- stmt.add_select('name')
447
- stmt.add_from('user')
448
- stmt.add_index_hint(:user => {:type => 'USE', :list => ['index_hint']})
449
- stmt.as_sql
450
- # => "SELECT name FROM user USE INDEX (index_hint)"
451
-
452
- =item C<< stmt.add_where('foo_id' => 'bar'); >>
453
-
454
- Add a new WHERE clause.
455
-
456
- stmt = SQL::Maker::Select.new.add_select('c')
457
- .add_from('foo')
458
- .add_where('name' => 'john')
459
- .add_where('type' => {:IN => %w/1 2 3/})
460
- .as_sql
461
- # => "SELECT c FROM foo WHERE (name = ?) AND (type IN (?, ?, ?))"
462
-
463
- =item C<< stmt.add_where_raw('id = ?', [1]) >>
464
-
465
- Add a new WHERE clause from raw placeholder string and bind variables.
466
-
467
- stmt = SQL::Maker::Select.new.add_select('c')
468
- .add_from('foo')
469
- .add_where_raw('EXISTS(SELECT * FROM bar WHERE name = ?)' => ['john'])
470
- .add_where_raw('type IS NOT NULL')
471
- .as_sql
472
- # => "SELECT c FROM foo WHERE (EXISTS(SELECT * FROM bar WHERE name = ?)) AND (type IS NOT NULL)"
473
-
474
-
475
- =item C<< stmt.set_where(condition) >>
476
-
477
- Set the WHERE clause.
478
-
479
- condition should be instance of L<SQL::Maker::Condition>.
480
-
481
- cond1 = SQL::Maker::Condition.new.add("name" => "john")
482
- cond2 = SQL::Maker::Condition.new.add("type" => {:IN => %w/1 2 3/})
483
- stmt = SQL::Maker::Select.new.add_select('c')
484
- .add_from('foo')
485
- .set_where(cond1 & cond2)
486
- .as_sql
487
- # => "SELECT c FROM foo WHERE ((name = ?)) AND ((type IN (?, ?, ?)))"
488
-
489
- =item C<< stmt.add_order_by('foo'); >>
490
-
491
- =item C<< stmt.add_order_by({'foo' => 'DESC'}); >>
492
-
493
- Add a new ORDER BY clause.
494
-
495
- stmt = SQL::Maker::Select.new.add_select('c')
496
- .add_from('foo')
497
- .add_order_by('name' => 'DESC')
498
- .add_order_by('id')
499
- .as_sql
500
- # => "SELECT c FROM foo ORDER BY name DESC, id"
501
-
502
- =item C<< stmt.add_group_by('foo'); >>
503
-
504
- Add a new GROUP BY clause.
505
-
506
- stmt = SQL::Maker::Select.new.add_select('c')
507
- .add_from('foo')
508
- .add_group_by('id')
509
- .as_sql
510
- # => "SELECT c FROM foo GROUP BY id"
511
-
512
- stmt = SQL::Maker::Select.new.add_select('c')
513
- .add_from('foo')
514
- .add_group_by('id' => 'DESC')
515
- .as_sql
516
- # => "SELECT c FROM foo GROUP BY id DESC"
517
-
518
- =item C<< stmt.limit(30) >>
519
-
520
- =item C<< stmt.offset(5) >>
521
-
522
- Add LIMIT and OFFSET.
523
-
524
- stmt = SQL::Maker::Select.new.add_select('c')
525
- .add_from('foo')
526
- .limit(30)
527
- .offset(5)
528
- .as_sql
529
- # => "SELECT c FROM foo LIMIT 30 OFFSET 5"
530
-
531
- =item C<< stmt.add_having(:cnt => 2) >>
532
-
533
- Add a HAVING clause.
534
-
535
- # stmt = SQL::Maker::Select.new.add_from('foo')
536
- # .add_select(\'COUNT(*)' => 'cnt')
537
- # .add_having(:cnt => 2)
538
- # .as_sql
539
- # # => "SELECT COUNT(*) AS cnt FROM foo HAVING (COUNT(*) = ?)"
540
-
541
- =back
542
-
543
- =head1 SEE ALSO
544
-
545
- L<Data::ObjectDriver::SQL>
@@ -76,119 +76,3 @@ class SQL::Maker::SelectSet
76
76
  self # method chain
77
77
  end
78
78
  end
79
-
80
- __END__
81
-
82
- =head1 NAME
83
-
84
- SQL::Maker::SelectSet - provides set functions
85
-
86
- =head1 SYNOPSIS
87
-
88
- use SQL::Maker::SelectSet qw(union_all except)
89
- s1 = SQL::Maker::Select .new()
90
- .add_select('foo')
91
- .add_from('t1')
92
- s2 = SQL::Maker::Select .new()
93
- .add_select('bar')
94
- .add_from('t2')
95
- union_all( s1, s2 ).as_sql
96
- # =>
97
- # SQL::Maker::SelectSet.new_set(
98
- # :operator => 'UNION ALL',
99
- # :new_line => s1.new_line
100
- # ).add_statement(s1)
101
- # .add_statement(s2)
102
- # .as_sql
103
- # => "SELECT foo FROM t1 UNION ALL SELECT bar FROM t2"
104
- except( s1, s2 ).as_sql
105
- # => SQL::Maker::SelectSet.new_set( :operator => 'EXCEPT', :new_line => s1.new_line )
106
- # .add_statement( s1 )
107
- # .add_statement( s2 )
108
- # .as_sql
109
- # => "SELECT foo FROM t1 EXCEPT SELECT bar FROM t2"
110
-
111
- =head1 DESCRIPTION
112
-
113
- This module provides some set functions which return a SQL::Maker::SelectSet object
114
- inherited from L<SQL::Maker::Select>.
115
-
116
- =head1 FUNCTION
117
-
118
- =over 4
119
-
120
- =item C<< union(select :SQL::Maker::Select | set :SQL::Maker::SelectSet) : SQL::Maker::SelectSet >>
121
-
122
- Tow statements are combined by C<UNION>.
123
-
124
- =item C<< union_all(select :SQL::Maker::Select | set :SQL::Maker::SelectSet) : SQL::Maker::SelectSet >>
125
-
126
- Tow statements are combined by C<UNION ALL>.
127
-
128
- =item C<< intersect(select :SQL::Maker::Select | set :SQL::Maker::SelectSet) : SQL::Maker::SelectSet >>
129
-
130
- Tow statements are combined by C<INTERSECT>.
131
-
132
- =item C<< intersect_all(select :SQL::Maker::Select | set :SQL::Maker::SelectSet) : SQL::Maker::SelectSet >>
133
-
134
- Tow statements are combined by C<INTERSECT ALL>.
135
-
136
- =item C<< except(select :SQL::Maker::Select | set :SQL::Maker::SelectSet) : SQL::Maker::SelectSet >>
137
-
138
- Tow statements are combined by C<EXCEPT>.
139
-
140
- =item C<< except(select :SQL::Maker::Select | set :SQL::Maker::SelectSet) : SQL::Maker::SelectSet >>
141
-
142
- Tow statements are combined by C<EXCEPT ALL>.
143
-
144
- =back
145
-
146
- =head1 Class Method
147
-
148
- =over 4
149
-
150
- =item stmt = SQL::Maker::SelectSet.new( %args )
151
-
152
- opretaor is a set operator (ex. C<UNION>).
153
- one and another are SQL::Maker::Select object or SQL::Maker::SelectSet object.
154
- It returns a SQL::Maker::SelectSet object.
155
-
156
- The parameters are:
157
-
158
- =over 4
159
-
160
- =item new_line
161
-
162
- Default values is "\n".
163
-
164
- =item operator : Str
165
-
166
- The operator. This parameter is required.
167
-
168
- =back
169
-
170
- =back
171
-
172
- =head1 Instance Methods
173
-
174
- =over 4
175
-
176
- =item C<< sql = set.as_sql() : Str >>
177
-
178
- Returns a new select statement.
179
-
180
- =item C<< @bind = set.bind() : Array[Str] >>
181
-
182
- Returns bind variables.
183
-
184
- =item C<< set.add_statement(stmt : stmt.can('as_sql')) : SQL::Maker::SelectSet >>
185
-
186
- This method adds new statement object. C<< stmt >> must provides 'as_sql' method.
187
-
188
- I<Return Value> is the set itself.
189
-
190
- =back
191
-
192
- =head1 SEE ALSO
193
-
194
- L<SQL::Maker::Select>
@@ -161,6 +161,8 @@ class SQL::QueryMaker
161
161
  }, bind)
162
162
  end
163
163
 
164
+ # sql_raw('SELECT foo_id FROM bar WHERE t=44')
165
+ # sql_raw('SELECT foo_id FROM bar WHERE t=?', [44])
164
166
  def sql_raw(*args)
165
167
  sql, bind = parse_args(*args)
166
168
  return SQL::QueryMaker.new(nil, Proc.new { sql }, bind)
@@ -206,224 +208,3 @@ class SQL::QueryMaker
206
208
  label.to_s.split(/\./).map {|e| "`#{e}`"}.join('.')
207
209
  end
208
210
  end
209
-
210
- __END__
211
-
212
- =head1 NAME
213
-
214
- SQL::QueryMaker - helper functions for SQL query generation
215
-
216
- =head1 SYNOPSIS
217
-
218
- query = sql_eq(:foo => v)
219
- query.as_sql # `foo`=?
220
- query.bind # (v)
221
-
222
- query = sql_lt(:foo => v)
223
- query.as_sql # `foo`<?
224
- query.bind # (v)
225
-
226
- query = sql_in(:foo => [
227
- v1, v2, v3,
228
- ])
229
- query.as_sql # `foo` IN (?,?,?)
230
- query.bind # (v1,v2,v3)
231
-
232
- query = sql_and(:foo => [
233
- sql_ge(min),
234
- sql_lt(max)
235
- ])
236
- query.as_sql # `foo`>=? AND `foo`<?
237
- query.bind # (min,max)
238
-
239
- query = sql_and([
240
- sql_eq(:foo => v1),
241
- sql_eq(:bar => v2)
242
- ]
243
- query.as_sql # `foo`=? AND `bar`=?
244
- query.bind # (v1,v2)
245
-
246
- query = sql_and([
247
- :foo => v1,
248
- :bar => sql_lt(v2),
249
- ])
250
- query.as_sql # `foo`=? AND `bar`<?
251
- query.bind # (v1,v2)
252
-
253
- =head1 DESCRIPTION
254
-
255
- This module concentrates on providing an expressive, concise way to declare SQL
256
- expressions by exporting carefully-designed functions.
257
- It is possible to use the module to generate SQL query conditions and pass them
258
- as arguments to other more versatile query builders such as L<SQL::Maker>.
259
-
260
- The functions exported by the module instantiate comparator objects that build
261
- SQL expressions when their C<as_sql> method are being invoked.
262
- There are two ways to specify the names of the columns to the comparator; to
263
- pass in the names as argument or to specify then as an argument to the
264
- C<as_sql> method.
265
-
266
- =head1 FUNCTIONS
267
-
268
- =head2 C<< sql_eq([column,] value) >>
269
-
270
- =head2 C<< sql_lt([column,] value) >>
271
-
272
- =head2 C<< sql_gt([column,] value) >>
273
-
274
- =head2 C<< sql_le([column,] value) >>
275
-
276
- =head2 C<< sql_ge([column,] value) >>
277
-
278
- =head2 C<< sql_like([column,] value) >>
279
-
280
- =head2 C<< sql_is_null([column]) >>
281
-
282
- =head2 C<< sql_is_not_null([column]) >>
283
-
284
- =head2 C<< sql_not([column]) >>
285
-
286
- =head2 C<< sql_between([column,] min_value, max_value) >>
287
-
288
- =head2 C<< sql_not_between([column,] min_value, max_value) >>
289
-
290
- =head2 C<< sql_in([column,] \@values) >>
291
-
292
- =head2 C<< sql_not_in([column,] \@values) >>
293
-
294
- Instantiates a comparator object that tests a column against given value(s).
295
-
296
- =head2 C<< sql_and([column,] \@conditions) >>
297
-
298
- =head2 C<< sql_or([$ column,] \@conditions) >>
299
-
300
- Aggregates given comparator objects into a logical expression.
301
-
302
- If specified, the column name is pushed down to the arguments when the
303
- C<as_sql> method is being called, as show in the second example below.
304
-
305
- sql_and([ # => `foo`=? AND `bar`<?
306
- sql_eq("foo" => v1),
307
- sql_lt("bar" => v2)
308
- ])
309
-
310
- sql_and("foo" => [ # => `foo`>=min OR `foo`<max
311
- sql_ge(min),
312
- sql_lt(max),
313
- ])
314
-
315
- =head2 C<< sql_and(\%conditions) >>
316
-
317
- =head2 C<< sql_or(\%conditions) >>
318
-
319
- Aggregates given pairs of column names and comparators into a logical
320
- expression.
321
-
322
- The value part is composed of as the argument to the C<=> operator if it is
323
- not a blessed reference.
324
-
325
- query = sql_and({
326
- :foo => 'abc',
327
- :bar => sql_lt(123),
328
- })
329
- query.as_sql # => `foo`=? AND bar<?
330
- query.bind # => ('abc', 123)
331
-
332
-
333
- =head2 C<< sql_op([column,] op_sql, \@bind_values) >>
334
-
335
- Generates a comparator object that tests a column using the given SQL and
336
- values. C<<@>> in the given SQL are replaced by the column name (specified
337
- either by the argument to the function or later by the call to the C<<as_sql>>
338
- method), and C<<?>> are substituted by the given bind values.
339
-
340
- =head2 C<< sql_raw(sql, @bind_values) >>
341
-
342
- Generates a comparator object from raw SQL and bind values. C<<?>> in the
343
- given SQL are replaced by the bind values.
344
-
345
- =head2 C<< obj.as_sql() >>
346
-
347
- =head2 C<< obj.as_sql(column_name) >>
348
-
349
- =head2 C<< obj.as_sql(column_name, quote_identifier_cb) >>
350
-
351
- Compiles given comparator object and returns an SQL expression.
352
- Corresponding bind values should be obtained by calling the C<bind> method.
353
-
354
- The function optionally accepts a column name to which the comparator object
355
- should be bound; an error is thrown if the comparator object is already bound
356
- to another column.
357
-
358
- The function also accepts a callback for quoting the identifiers. If omitted,
359
- the identifiers are quoted using C<`> after being splitted using C<.>; i.e. a
360
- column designated as C<foo.bar> is quoted as C<`foo`.`bar`>.
361
-
362
- =head2 C<< obj.bind() >>
363
-
364
- Returns a list of bind values corresponding to the SQL expression returned by
365
- the C<as_sql> method.
366
-
367
- =head1 CHEAT SHEET
368
-
369
- IN: sql_eq('foo' => 'bar')
370
- OUT QUERY: '`foo` = ?'
371
- OUT BIND: ['bar']
372
-
373
- IN: sql_in('foo' => ['bar', 'baz'])
374
- OUT QUERY: '`foo` IN (?,?)'
375
- OUT BIND: ['bar','baz']
376
-
377
- IN: sql_and([sql_eq('foo' => 'bar'), sql_eq('baz' => 123)])
378
- OUT QUERY: '(`foo` = ?) AND (`baz` = ?)'
379
- OUT BIND: ['bar',123]
380
-
381
- IN: sql_and('foo' => [sql_ge(3), sql_lt(5)])
382
- OUT QUERY: '(`foo` >= ?) AND (`foo` < ?)'
383
- OUT BIND: [3,5]
384
-
385
- IN: sql_or([sql_eq('foo' => 'bar'), sql_eq('baz' => 123)])
386
- OUT QUERY: '(`foo` = ?) OR (`baz` = ?)'
387
- OUT BIND: ['bar',123]
388
-
389
- IN: sql_or('foo' => ['bar', 'baz'])
390
- OUT QUERY: '(`foo` = ?) OR (`foo` = ?)'
391
- OUT BIND: ['bar','baz']
392
-
393
- IN: sql_is_null('foo')
394
- OUT QUERY: '`foo` IS NULL'
395
- OUT BIND: []
396
-
397
- IN: sql_is_not_null('foo')
398
- OUT QUERY: '`foo` IS NOT NULL'
399
- OUT BIND: []
400
-
401
- IN: sql_between('foo', 1, 2)
402
- OUT QUERY: '`foo` BETWEEN ? AND ?'
403
- OUT BIND: [1,2]
404
-
405
- IN: sql_not('foo')
406
- OUT QUERY: 'NOT `foo`'
407
- OUT BIND: []
408
-
409
- IN: sql_op('apples', 'MATCH (@) AGAINST (?)', ['oranges'])
410
- OUT QUERY: 'MATCH (`apples`) AGAINST (?)'
411
- OUT BIND: ['oranges']
412
-
413
- IN: sql_raw('SELECT * FROM t WHERE id=?',123)
414
- OUT QUERY: 'SELECT * FROM t WHERE id=?'
415
- OUT BIND: [123]
416
-
417
- IN: sql_in('foo' => [123,sql_raw('SELECT id FROM t WHERE cat=?',5)])
418
- OUT QUERY: '`foo` IN (?,(SELECT id FROM t WHERE cat=?))'
419
- OUT BIND: [123,5]
420
-
421
- =head1 AUTHOR
422
-
423
- Natoshi Seo (Originally designed by Kazuho Oku as a Perl module)
424
-
425
- =head1 LICENSE
426
-
427
- This library is free software; you can redistribute it and/or modify it under the MIT License.
428
-
429
- =cut