twowaysql 0.2.0

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.
Files changed (39) hide show
  1. data/History.txt +3 -0
  2. data/License.txt +13 -0
  3. data/Manifest.txt +38 -0
  4. data/README.txt +382 -0
  5. data/Rakefile +4 -0
  6. data/config/hoe.rb +73 -0
  7. data/config/requirements.rb +15 -0
  8. data/issues/issue-25efcfc383f3b0f6c0e2730ae7c2975bb2b3de26.yaml +18 -0
  9. data/issues/issue-39023ea09e17e2d64bcef03aa59cdfe38b78ad5b.yaml +26 -0
  10. data/issues/issue-4bc308d55ae91f266e656162a4147d356de1166c.yaml +24 -0
  11. data/issues/issue-897995fa10377eabdf597e8e7692f17087c76923.yaml +26 -0
  12. data/issues/issue-bd38c1cdc965d73dd629a81db2de1bcdcf4b10b8.yaml +26 -0
  13. data/issues/issue-f2b773020b54f839c03d899b38b5113c8fd991df.yaml +18 -0
  14. data/issues/issue-f39b907d01d7fa93df8c7a9de2e1b5e27727ee0a.yaml +18 -0
  15. data/issues/issue-f64d73ed4f9854f1ded77e6496dbf59cfb3770a7.yaml +18 -0
  16. data/issues/project.yaml +16 -0
  17. data/lib/twowaysql/node.rb +239 -0
  18. data/lib/twowaysql/parser.rb +489 -0
  19. data/lib/twowaysql/parser.y +226 -0
  20. data/lib/twowaysql/template.rb +75 -0
  21. data/lib/twowaysql/version.rb +9 -0
  22. data/lib/twowaysql.rb +6 -0
  23. data/script/console +10 -0
  24. data/script/destroy +14 -0
  25. data/script/generate +14 -0
  26. data/script/txt2html +82 -0
  27. data/setup.rb +1585 -0
  28. data/spec/large_sql_spec.rb +142 -0
  29. data/spec/learning_regex_spec.rb +234 -0
  30. data/spec/spec.opts +0 -0
  31. data/spec/spec_helper.rb +10 -0
  32. data/spec/twowaysql_spec.rb +736 -0
  33. data/tasks/deployment.rake +53 -0
  34. data/tasks/ditz.rake +8 -0
  35. data/tasks/environment.rake +7 -0
  36. data/tasks/racc.rake +23 -0
  37. data/tasks/rspec.rake +21 -0
  38. data/tasks/website.rake +17 -0
  39. metadata +104 -0
@@ -0,0 +1,736 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+
4
+ describe TwoWaySQL::Template do
5
+
6
+ before do
7
+ @ctx = {}
8
+ end
9
+
10
+
11
+
12
+ describe "when parse SQL without comment nodes, e.g. 'SELECT * FROM emp'" do
13
+ before do
14
+ sql = "SELECT * FROM emp"
15
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
16
+ @result = @template.merge(@ctx)
17
+ end
18
+
19
+ it "should not change original sql" do
20
+ @result.sql.should == "SELECT * FROM emp"
21
+ end
22
+
23
+ it "should have empty bound valiables" do
24
+ @result.bound_variables.should be_empty
25
+ end
26
+ end
27
+
28
+
29
+
30
+ describe "when parsed from 'SELECT * FROM emp WHERE job = /*ctx[:job]*/'CLERK' AND deptno = /*ctx[:deptno]*/20'" do
31
+ before do
32
+ sql = "SELECT * FROM emp WHERE job = /*ctx[:job]*/'CLERK' AND deptno = /*ctx[:deptno]*/20"
33
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
34
+ end
35
+
36
+ describe "pass Context with Symbol keys like ctx[:job] = 'HOGE' and ctx[:deptno] = 30" do
37
+ before do
38
+ @ctx[:job] = "HOGE"
39
+ @ctx[:deptno] = 30
40
+ @result = @template.merge(@ctx)
41
+ end
42
+
43
+ it "should parse '/*' as comment start and '*/' as comment end, then replace them with question mark. so SQL will 'SELECT * FROM emp WHERE job = ? AND deptno = ?'" do
44
+ @result.sql.should == "SELECT * FROM emp WHERE job = ? AND deptno = ?"
45
+ end
46
+
47
+ it "should have two bound variables in Array ['HOGE', 30]" do
48
+ @result.bound_variables.should == ["HOGE", 30]
49
+ end
50
+ end
51
+ end
52
+
53
+
54
+
55
+ describe "when parsed from 'SELECT * FROM emp WHERE job = /*ctx['job']*/'CLERK' AND deptno = /*ctx['deptno']*/20'" do
56
+ before do
57
+ sql = "SELECT * FROM emp WHERE job = /*ctx['job']*/'CLERK' AND deptno = /*ctx['deptno']*/20"
58
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
59
+ end
60
+
61
+ describe "pass Context with String keys like ctx['job'] = 'HOGE' and ctx['deptno'] = 30" do
62
+ before do
63
+ @ctx['job'] = "HOGE"
64
+ @ctx['deptno'] = 30
65
+ @result = @template.merge(@ctx)
66
+ end
67
+
68
+ it "should parse '/*' as comment start and '*/' as comment end, then replace them with question mark. so SQL will 'SELECT * FROM emp WHERE job = ? AND deptno = ?'" do
69
+ @result.sql.should == "SELECT * FROM emp WHERE job = ? AND deptno = ?"
70
+ end
71
+
72
+ it "should have two bound variables in Array ['HOGE', 30]" do
73
+ @result.bound_variables.should == ["HOGE", 30]
74
+ end
75
+ end
76
+ end
77
+
78
+
79
+
80
+ describe "when parsed from 'SELECT * FROM emp WHERE job = #*ctx[:job]*#'CLERK' AND deptno = #*ctx[:deptno]*#20'" do
81
+ before do
82
+ sql = "SELECT * FROM emp WHERE job = #*ctx[:job]*#'CLERK' AND deptno = #*ctx[:deptno]*#20"
83
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
84
+
85
+ @ctx[:job] = "HOGE"
86
+ @ctx[:deptno] = 30
87
+ @result = @template.merge(@ctx)
88
+ end
89
+
90
+ it "should parse '#*' as comment start and '*#' as comment end, then replace them with question mark. so SQL will 'SELECT * FROM emp WHERE job = ? AND deptno = ?'" do
91
+ @result.sql.should == 'SELECT * FROM emp WHERE job = ? AND deptno = ?'
92
+ end
93
+
94
+ it "should have two variables" do
95
+ @result.bound_variables.size.should == 2
96
+ end
97
+
98
+ it "should have two bound variables in Array" do
99
+ @result.bound_variables.should == ["HOGE", 30]
100
+ end
101
+ end
102
+
103
+
104
+
105
+ describe "when parsed from SQL file with one or more white speces in comment, like 'SELECT * FROM emp WHERE job = /* ctx[:job]*/'CLERK''" do
106
+ before do
107
+ sql = "SELECT * FROM emp WHERE job = /* ctx[:job]*/'CLERK'"
108
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
109
+
110
+ @ctx[:job] = "HOGE"
111
+ @result = @template.merge(@ctx)
112
+ end
113
+
114
+ it "should treat comment node which starts with one or more speces like /* ctx[:job]*/'CLERK' as real comment node, therefore it does *NOT* replace comment node with question mark. so SQL will 'SELECT * FROM emp WHERE job = 'CLERK''" do
115
+ @result.sql.should == "SELECT * FROM emp WHERE job = 'CLERK'"
116
+ end
117
+
118
+ it "should have no variable nodes, so return empty Array as bound variables" do
119
+ @result.bound_variables.should be_empty
120
+ end
121
+ end
122
+
123
+
124
+
125
+ describe "when parsed from 'SELECT * FROM emp WHERE empno = /*ctx[:empno]*/1 AND 1 = 1'" do
126
+ before do
127
+ sql = "SELECT * FROM emp WHERE empno = /*ctx[:empno]*/1 AND 1 = 1"
128
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
129
+
130
+ @ctx[:empno] = 7788
131
+ @result = @template.merge(@ctx)
132
+ end
133
+
134
+ it "parsed SQL should 'SELECT * FROM emp WHERE empno = ? AND 1 = 1'" do
135
+ @result.sql.should == 'SELECT * FROM emp WHERE empno = ? AND 1 = 1'
136
+ end
137
+
138
+ it "should have bound variables in Array [7788]" do
139
+ @result.bound_variables.should == [7788]
140
+ end
141
+ end
142
+
143
+
144
+
145
+ describe "when parsed from 'SELECT * FROM emp/*IF ctx[:job] */ WHERE job = /*ctx[:job]*/'CLERK'/*END*/'" do
146
+ before do
147
+ sql = "SELECT * FROM emp/*IF ctx[:job] */ WHERE job = /*ctx[:job]*/'CLERK'/*END*/"
148
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
149
+ end
150
+
151
+ describe "and when :job param exists" do
152
+ before do
153
+ @ctx[:job] = "HOGE"
154
+ @result = @template.merge(@ctx)
155
+ end
156
+ it "parsed SQL should 'SELECT * FROM emp WHERE job = ?'" do
157
+ @result.sql.should == 'SELECT * FROM emp WHERE job = ?'
158
+ end
159
+ it "should have bound variables in Array ['HOGE']" do
160
+ @result.bound_variables.should == ['HOGE']
161
+ end
162
+ end
163
+
164
+ describe "and when :job param does not exist" do
165
+ before do
166
+ @result = @template.merge(@ctx)
167
+ end
168
+ it "parsed SQL should 'SELECT * FROM emp'" do
169
+ @result.sql.should == 'SELECT * FROM emp'
170
+ end
171
+ it "bound variables should be empty" do
172
+ @result.bound_variables.should be_empty
173
+ end
174
+ end
175
+ end
176
+
177
+
178
+
179
+ describe "when parsed from SQL with 'nested if' like '/*IF ctx[:aaa]*/aaa/*IF ctx[:bbb]*/bbb/*END*//*END*/'" do
180
+ before do
181
+ sql = "/*IF ctx[:aaa]*/aaa/*IF ctx[:bbb]*/bbb/*END*//*END*/"
182
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
183
+ end
184
+
185
+ describe "and when inner is true but outer is false" do
186
+ before do
187
+ @ctx[:bbb] = "hoge"
188
+ @result = @template.merge(@ctx)
189
+ end
190
+ it "parsed SQL should be empty'" do
191
+ @result.sql.should be_empty
192
+ end
193
+ it "bound variables is empty too" do
194
+ @result.bound_variables.should be_empty
195
+ end
196
+ end
197
+
198
+ describe "and when outer is true and inner is false" do
199
+ before do
200
+ @ctx[:aaa] = "hoge"
201
+ @result = @template.merge(@ctx)
202
+ end
203
+ it "parsed SQL should be 'aaa'" do
204
+ @result.sql.should == 'aaa'
205
+ end
206
+ it "should have no bound variables because there is no assignments" do
207
+ @result.bound_variables.should be_empty
208
+ end
209
+ end
210
+
211
+ describe "and when both outer and inner is true" do
212
+ before do
213
+ @ctx[:aaa] = "hoge"
214
+ @ctx[:bbb] = "foo"
215
+ @result = @template.merge(@ctx)
216
+ end
217
+ it "parsed SQL should be 'aaabbb'" do
218
+ @result.sql.should == 'aaabbb'
219
+ end
220
+ it "should have no bound variables because there is no assignments" do
221
+ @result.bound_variables.should be_empty
222
+ end
223
+ end
224
+
225
+ end
226
+
227
+
228
+
229
+ describe "when parsed from 'SELECT * FROM emp WHERE /*IF ctx[:job]*/job = /*ctx[:job]*/'CLERK'-- ELSE job is null/*END*/'" do
230
+ before do
231
+ sql = "SELECT * FROM emp WHERE /*IF ctx[:job]*/job = /*ctx[:job]*/'CLERK'-- ELSE job is null/*END*/"
232
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
233
+ end
234
+
235
+ describe "and when :job param exists" do
236
+ before do
237
+ @ctx[:job] = "HOGE"
238
+ @result = @template.merge(@ctx)
239
+ end
240
+ it "parsed SQL should 'SELECT * FROM emp WHERE job = ?'" do
241
+ @result.sql.should == 'SELECT * FROM emp WHERE job = ?'
242
+ end
243
+ it "should have bound variables in Array ['HOGE']" do
244
+ @result.bound_variables.should == ['HOGE']
245
+ end
246
+ end
247
+
248
+ describe "and when :job param does not exist" do
249
+ before do
250
+ @result = @template.merge(@ctx)
251
+ end
252
+ it "parsed SQL should 'SELECT * FROM emp WHERE job is null'" do
253
+ @result.sql.should == 'SELECT * FROM emp WHERE job is null'
254
+ end
255
+ it "bound variables should be empty" do
256
+ @result.bound_variables.should be_empty
257
+ end
258
+ end
259
+ end
260
+
261
+
262
+
263
+ describe "when parsed from '/*IF false*/aaa--ELSE bbb = /*ctx[:bbb]*/123/*END*/'" do
264
+ before do
265
+ sql = "/*IF false*/aaa--ELSE bbb = /*ctx[:bbb]*/123/*END*/"
266
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
267
+ end
268
+
269
+ describe "and when :bbb param exists" do
270
+ before do
271
+ @ctx[:bbb] = 123
272
+ @result = @template.merge(@ctx)
273
+ end
274
+ it "parsed SQL should 'bbb = ?'" do
275
+ @result.sql.should == 'bbb = ?'
276
+ end
277
+ it "should have bound variables in Array [123]" do
278
+ @result.bound_variables.should == [123]
279
+ end
280
+ end
281
+
282
+ describe "and when :bbb param does not exist" do
283
+ before do
284
+ @result = @template.merge(@ctx)
285
+ end
286
+ it "parsed SQL should also 'bbb = ?'" do
287
+ @result.sql.should == 'bbb = ?'
288
+ end
289
+ it "should have bound variables in Array, accidentally [nil]" do
290
+ @result.bound_variables.should == [nil]
291
+ end
292
+ end
293
+ end
294
+
295
+
296
+
297
+ describe "when parsed from '/*IF false*/aaa--ELSE bbb/*IF false*/ccc--ELSE ddd/*END*//*END*/'" do
298
+ before do
299
+ sql = "/*IF false*/aaa--ELSE bbb/*IF false*/ccc--ELSE ddd/*END*//*END*/"
300
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
301
+ @result = @template.merge(@ctx)
302
+ end
303
+
304
+ it "parsed SQL should 'bbbddd'" do
305
+ @result.sql.should == "bbbddd"
306
+ end
307
+ end
308
+
309
+
310
+
311
+ describe "when parsed from 'SELECT * FROM emp/*BEGIN*/ WHERE /*IF false*/aaa-- ELSE AND deptno = 10/*END*//*END*/'" do
312
+ before do
313
+ sql = "SELECT * FROM emp/*BEGIN*/ WHERE /*IF false*/aaa-- ELSE AND deptno = 10/*END*//*END*/"
314
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
315
+ @result = @template.merge(@ctx)
316
+ end
317
+
318
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno = 10'" do
319
+ @result.sql.should == "SELECT * FROM emp WHERE deptno = 10"
320
+ end
321
+ end
322
+
323
+ describe "when parsed from 'SELECT * FROM emp/*BEGIN*/ WHERE /*IF false*/aaa--- ELSE AND deptno = 10/*END*//*END*/'" do
324
+ before do
325
+ sql = "SELECT * FROM emp/*BEGIN*/ WHERE /*IF false*/aaa--- ELSE AND deptno = 10/*END*//*END*/"
326
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
327
+ @result = @template.merge(@ctx)
328
+ end
329
+
330
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno = 10'" do
331
+ @result.sql.should == "SELECT * FROM emp WHERE deptno = 10"
332
+ end
333
+ end
334
+
335
+
336
+
337
+ describe "when parsed from 'SELECT * FROM emp/*BEGIN*/ WHERE /*IF ctx[:job]*/job = /*ctx[:job]*/'CLERK'/*END*//*IF ctx[:deptno]*/ AND deptno = /*ctx[:deptno]*/20/*END*//*END*/'" do
338
+ before do
339
+ sql = "SELECT * FROM emp/*BEGIN*/ WHERE /*IF ctx[:job]*/job = /*ctx[:job]*/'CLERK'/*END*//*IF ctx[:deptno]*/ AND deptno = /*ctx[:deptno]*/20/*END*//*END*/"
340
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
341
+ end
342
+
343
+ describe "and when context is empty (no param exists)" do
344
+ before do
345
+ @result = @template.merge(@ctx)
346
+ end
347
+ it "parsed SQL should 'SELECT * FROM emp'" do
348
+ @result.sql.should == 'SELECT * FROM emp'
349
+ end
350
+ it "bound variables should be empty" do
351
+ @result.bound_variables.should be_empty
352
+ end
353
+ end
354
+
355
+ describe "and when :job param exists" do
356
+ before do
357
+ @ctx[:job] = "HOGE"
358
+ @result = @template.merge(@ctx)
359
+ end
360
+ it "parsed SQL should 'SELECT * FROM emp WHERE job = ?'" do
361
+ @result.sql.should == 'SELECT * FROM emp WHERE job = ?'
362
+ end
363
+ it "should have bound variables in Array ['HOGE']" do
364
+ @result.bound_variables.should == ['HOGE']
365
+ end
366
+ end
367
+
368
+ describe "and when :job and :deptno param exists" do
369
+ before do
370
+ @ctx[:job] = "HOGE"
371
+ @ctx[:deptno] = 20
372
+ @result = @template.merge(@ctx)
373
+ end
374
+ it "parsed SQL should 'SELECT * FROM emp WHERE job = ? AND deptno = ?'" do
375
+ @result.sql.should == 'SELECT * FROM emp WHERE job = ? AND deptno = ?'
376
+ end
377
+ it "should have bound variables in Array ['HOGE',20]" do
378
+ @result.bound_variables.should == ['HOGE',20]
379
+ end
380
+ end
381
+
382
+ describe "and when :job param does not exist and :deptno param exists" do
383
+ before do
384
+ @ctx[:deptno] = 20
385
+ @result = @template.merge(@ctx)
386
+ end
387
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno = ?'" do
388
+ @result.sql.should == 'SELECT * FROM emp WHERE deptno = ?'
389
+ end
390
+ it "should have bound variables in Array [20]" do
391
+ @result.bound_variables.should == [20]
392
+ end
393
+ end
394
+ end
395
+
396
+
397
+
398
+ describe "when parsed from '/*BEGIN*/WHERE /*IF true*/aaa BETWEEN /*ctx[:bbb]*/111 AND /*ctx[:ccc]*/123/*END*//*END*/'" do
399
+ before do
400
+ sql = "/*BEGIN*/WHERE /*IF true*/aaa BETWEEN /*ctx[:bbb]*/111 AND /*ctx[:ccc]*/123/*END*//*END*/"
401
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
402
+ end
403
+
404
+ describe "and when :job and :deptno param exists" do
405
+ before do
406
+ @ctx[:bbb] = 300
407
+ @ctx[:ccc] = 400
408
+ @result = @template.merge(@ctx)
409
+ end
410
+ it "parsed SQL should 'WHERE aaa BETWEEN ? AND ?'" do
411
+ @result.sql.should == "WHERE aaa BETWEEN ? AND ?"
412
+ end
413
+ it "should have bound variables in Array [300,400]" do
414
+ @result.bound_variables.should == [300,400]
415
+ end
416
+ end
417
+
418
+ describe "and when :job and :deptno param does not exist" do
419
+ before do
420
+ @result = @template.merge(@ctx)
421
+ end
422
+ it "parsed SQL should 'WHERE aaa BETWEEN ? AND ?'" do
423
+ @result.sql.should == "WHERE aaa BETWEEN ? AND ?"
424
+ end
425
+ it "should have bound variables in Array, accidentally [nil,nil]" do
426
+ @result.bound_variables.should == [nil,nil]
427
+ end
428
+ end
429
+
430
+ end
431
+
432
+
433
+
434
+ describe "when parsed from 'SELECT * FROM emp WHERE deptno IN /*ctx[:deptnoList]*/(10, 20) ORDER BY ename'" do
435
+ before do
436
+ sql = "SELECT * FROM emp WHERE deptno IN /*ctx[:deptnoList]*/(10, 20) ORDER BY ename"
437
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
438
+ end
439
+
440
+ describe "and when :deptnoList param is [30,40,50]" do
441
+ before do
442
+ @ctx[:deptnoList] = [30,40,50]
443
+ @result = @template.merge(@ctx)
444
+ end
445
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno IN (?, ?, ?) ORDER BY ename'" do
446
+ @result.sql.should == "SELECT * FROM emp WHERE deptno IN (?, ?, ?) ORDER BY ename"
447
+ end
448
+ it "should have bound variables in Array [30,40,50]" do
449
+ @result.bound_variables.should == [30,40,50]
450
+ end
451
+ end
452
+
453
+ describe "and when :deptnoList param is [30]" do
454
+ before do
455
+ @ctx[:deptnoList] = [30]
456
+ @result = @template.merge(@ctx)
457
+ end
458
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno IN (?) ORDER BY ename'" do
459
+ @result.sql.should == "SELECT * FROM emp WHERE deptno IN (?) ORDER BY ename"
460
+ end
461
+ it "should have bound variables in Array [30]" do
462
+ @result.bound_variables.should == [30]
463
+ end
464
+ end
465
+
466
+ describe "and when :deptnoList param is empty" do
467
+ before do
468
+ @ctx[:deptnoList] = []
469
+ @result = @template.merge(@ctx)
470
+ end
471
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno IN ORDER BY ename' and *CAUSES SYNTAX ERROR* (use IF comment to avoid this)" do
472
+ @result.sql.should == "SELECT * FROM emp WHERE deptno IN ORDER BY ename"
473
+ end
474
+ it "bound variables should be empty" do
475
+ @result.bound_variables.should be_empty
476
+ end
477
+ end
478
+
479
+ describe "and when :deptnoList param does not exist" do
480
+ before do
481
+ @result = @template.merge(@ctx)
482
+ end
483
+ it "parsed SQL should 'SELECT * FROM emp WHERE deptno IN ORDER BY ename' and *CAUSES SYNTAX ERROR* (use IF comment to avoid this)" do
484
+ @result.sql.should == "SELECT * FROM emp WHERE deptno IN ORDER BY ename"
485
+ end
486
+ it "bound variables should be empty" do
487
+ @result.bound_variables.should be_empty
488
+ end
489
+ end
490
+
491
+ end
492
+
493
+
494
+
495
+ describe "when parsed from 'SELECT * FROM emp WHERE ename IN /*ctx[:enames]*/('SCOTT','MARY') AND job IN /*ctx[:jobs]*/('ANALYST', 'FREE')'" do
496
+ before do
497
+ sql = "SELECT * FROM emp WHERE ename IN /*ctx[:enames]*/('SCOTT','MARY') AND job IN /*ctx[:jobs]*/('ANALYST', 'FREE')"
498
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
499
+ end
500
+
501
+ describe "and when :enames param is ['DAVE', 'MARY', 'SCOTT'] and :jobs param is ['MANAGER', 'ANALYST']" do
502
+ before do
503
+ @ctx[:enames] = ['DAVE', 'MARY', 'SCOTT']
504
+ @ctx[:jobs] = ['MANAGER', 'ANALYST']
505
+ @result = @template.merge(@ctx)
506
+ end
507
+ it "parsed SQL should 'SELECT * FROM emp WHERE ename IN (?, ?, ?) AND job IN (?, ?)'" do
508
+ @result.sql.should == "SELECT * FROM emp WHERE ename IN (?, ?, ?) AND job IN (?, ?)"
509
+ end
510
+ it "should have bound variables in Array ['DAVE', 'MARY', 'SCOTT', 'MANAGER', 'ANALYST']" do
511
+ @result.bound_variables.should == ['DAVE', 'MARY', 'SCOTT', 'MANAGER', 'ANALYST']
512
+ end
513
+ end
514
+ end
515
+
516
+
517
+
518
+ describe "when parsed from 'INSERT INTO ITEM (ID, NUM) VALUES (/*ctx[:id]*/1, /*ctx[:num]*/20)'" do
519
+ before do
520
+ sql = "INSERT INTO ITEM (ID, NUM) VALUES (/*ctx[:id]*/1, /*ctx[:num]*/20)"
521
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
522
+ end
523
+
524
+ describe "and when :id param is 0 and :num param is 1" do
525
+ before do
526
+ @ctx[:id] = 0
527
+ @ctx[:num] = 1
528
+ @result = @template.merge(@ctx)
529
+ end
530
+ it "parsed SQL should 'INSERT INTO ITEM (ID, NUM) VALUES (?, ?)'" do
531
+ @result.sql.should == "INSERT INTO ITEM (ID, NUM) VALUES (?, ?)"
532
+ end
533
+ it "should have bound variables in Array [0, 1]" do
534
+ @result.bound_variables.should == [0, 1]
535
+ end
536
+ end
537
+ end
538
+
539
+
540
+
541
+ describe "when parsed from SQL with embedded variable comment '/*$ctx[:aaa]*/foo'" do
542
+ before do
543
+ sql = "/*$ctx[:aaa]*/foo"
544
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
545
+ end
546
+
547
+ describe "and :aaa param is 'hoge'" do
548
+ before do
549
+ @ctx[:aaa] = 'hoge'
550
+ @result = @template.merge(@ctx)
551
+ end
552
+ it "parsed SQL should 'hoge'" do
553
+ @result.sql.should == "hoge"
554
+ end
555
+ end
556
+ end
557
+
558
+
559
+
560
+ describe "when parsed from SQL with embedded variable comment 'BETWEEN sal ? AND ?'" do
561
+ before do
562
+ sql = "BETWEEN sal ? AND ?"
563
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
564
+ end
565
+
566
+ describe "and ctx[1] = 0 and ctx[2] = 1000 (note: key starts with 1, not 0.)" do
567
+ before do
568
+ @ctx[1] = 0
569
+ @ctx[2] = 1000
570
+ @result = @template.merge(@ctx)
571
+ end
572
+ it "parsed SQL should 'BETWEEN sal ? AND ?'" do
573
+ @result.sql.should == "BETWEEN sal ? AND ?"
574
+ end
575
+ it "should have bound variables in Array [0, 1000]" do
576
+ @result.bound_variables.should == [0, 1000]
577
+ end
578
+ end
579
+ end
580
+
581
+
582
+
583
+ describe "when parsed from 'SELECT * FROM emp/*hoge'" do
584
+ it "should cause parse error" do
585
+ lambda {
586
+ TwoWaySQL::Template.parse("SELECT * FROM emp/*hoge")
587
+ }.should raise_error(Racc::ParseError)
588
+ end
589
+ end
590
+
591
+
592
+
593
+ describe "when parsed from '/*BEGIN*/'" do
594
+ it "should cause parse error" do
595
+ lambda {
596
+ TwoWaySQL::Template.parse("/*BEGIN*/")
597
+ }.should raise_error(Racc::ParseError)
598
+ end
599
+ end
600
+
601
+
602
+
603
+ describe "when parse SQL with semicolon, " do
604
+ describe "that ends with semicolon like 'SELECT * FROM emp;'" do
605
+ before do
606
+ sql = "SELECT * FROM emp;"
607
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
608
+ @result = @template.merge(@ctx)
609
+ end
610
+ it "should strip semicolon at input end" do
611
+ @result.sql.should == "SELECT * FROM emp"
612
+ end
613
+ end
614
+
615
+ describe "that ends with semicolon and tab like 'SELECT * FROM emp;\t'" do
616
+ before do
617
+ sql = "SELECT * FROM emp;\t"
618
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
619
+ @result = @template.merge(@ctx)
620
+ end
621
+ it "should strip semicolon and tab at input end" do
622
+ @result.sql.should == "SELECT * FROM emp"
623
+ end
624
+ end
625
+
626
+ describe "that ends with semicolon and spaces like 'SELECT * FROM emp; '" do
627
+ before do
628
+ sql = "SELECT * FROM emp; "
629
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
630
+ @result = @template.merge(@ctx)
631
+ end
632
+ it "should strip semicolon and spaces at input end" do
633
+ @result.sql.should == "SELECT * FROM emp"
634
+ end
635
+ end
636
+ end
637
+
638
+
639
+
640
+ describe "various characters" do
641
+ describe " '<>' " do
642
+ before do
643
+ sql = "SELECT * FROM emp WHERE job <> /*ctx[:job]*/'CLERK'"
644
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
645
+ @ctx[:job] = "HOGE"
646
+ @result = @template.merge(@ctx)
647
+ end
648
+
649
+ it "SQL will 'SELECT * FROM emp WHERE job <> ?'" do
650
+ @result.sql.should == "SELECT * FROM emp WHERE job <> ?"
651
+ end
652
+
653
+ it "should have two bound variables in Array ['HOGE']" do
654
+ @result.bound_variables.should == ["HOGE"]
655
+ end
656
+ end
657
+
658
+
659
+ describe "minus, such as -5 " do
660
+ before do
661
+ sql = "SELECT * FROM statistics WHERE degree = /*ctx[:degree]*/-5"
662
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
663
+ @ctx[:degree] = -10
664
+ @result = @template.merge(@ctx)
665
+ end
666
+
667
+ it "SQL will 'SELECT * FROM statistics WHERE degree = ?'" do
668
+ @result.sql.should == "SELECT * FROM statistics WHERE degree = ?"
669
+ end
670
+
671
+ it "should have two bound variables in Array [-10]" do
672
+ @result.bound_variables.should == [-10]
673
+ end
674
+ end
675
+
676
+
677
+ describe "quote escape, such as 'Let''s' " do
678
+ before do
679
+ sql = "SELECT * FROM comments WHERE message = /*ctx[:message]*/'Let''s GO'"
680
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
681
+ @ctx[:message] = "Hang'in there"
682
+ @result = @template.merge(@ctx)
683
+ end
684
+
685
+ it "SQL will 'SELECT * FROM comments WHERE message = ?'" do
686
+ @result.sql.should == "SELECT * FROM comments WHERE message = ?"
687
+ end
688
+
689
+ it "should have two bound variables in Array ['Hang'in there']" do
690
+ @result.bound_variables.should == ["Hang'in there"]
691
+ end
692
+ end
693
+
694
+ end
695
+
696
+
697
+
698
+ describe "when parsed from 'SELECT * FROM emp -- comments here'" do
699
+ before do
700
+ sql = "SELECT * FROM emp -- comments here"
701
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
702
+ end
703
+
704
+ describe "and when 'job' param does not exist" do
705
+ before do
706
+ @result = @template.merge(@ctx)
707
+ end
708
+ it "parsed SQL should 'SELECT * FROM emp -- comments here'" do
709
+ @result.sql.should == 'SELECT * FROM emp -- comments here'
710
+ end
711
+ it "bound variables should be empty" do
712
+ @result.bound_variables.should be_empty
713
+ end
714
+ end
715
+ end
716
+
717
+
718
+ describe "when parsed from 'SELECT * FROM emp WHERE empno = /*ctx[:empno]*/5.0 AND 1 = 1'" do
719
+ before do
720
+ sql = "SELECT * FROM emp WHERE empno = /*ctx[:empno]*/5.0 AND 1 = 1"
721
+ @template = TwoWaySQL::Template.parse(sql, :preserve_eol => false)
722
+
723
+ @ctx[:empno] = 7788
724
+ @result = @template.merge(@ctx)
725
+ end
726
+
727
+ it "parsed SQL should 'SELECT * FROM emp WHERE empno = ? AND 1 = 1'" do
728
+ @result.sql.should == 'SELECT * FROM emp WHERE empno = ? AND 1 = 1'
729
+ end
730
+
731
+ it "should have bound variables in Array [7788]" do
732
+ @result.bound_variables.should == [7788]
733
+ end
734
+ end
735
+
736
+ end