twowaysql 0.2.1 → 0.3.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.
@@ -11,21 +11,19 @@ module TwoWaySQL
11
11
 
12
12
  class Parser < Racc::Parser
13
13
 
14
- module_eval <<'..end lib/twowaysql/parser.y modeval..id33db4a3791', 'lib/twowaysql/parser.y', 138
14
+ module_eval <<'..end lib/twowaysql/parser.y modeval..idd0cee34b5c', 'lib/twowaysql/parser.y', 134
15
15
 
16
16
  require 'strscan'
17
17
 
18
18
  def initialize(opts={})
19
19
  opts = {
20
- :debug => true,
20
+ :debug => false,
21
21
  :preserve_space => true,
22
- :preserve_comment => true,
23
- :preserve_eol => true
22
+ :preserve_comment => false
24
23
  }.merge(opts)
25
24
  @yydebug = opts[:debug]
26
25
  @preserve_space = opts[:preserve_space]
27
26
  @preserve_comment = opts[:preserve_comment]
28
- @preserve_eol = opts[:preserve_eol]
29
27
  @num_questions = 0
30
28
  end
31
29
 
@@ -36,28 +34,30 @@ BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*/
36
34
  PAREN_BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*#{PAREN_EXAMPLE}/
37
35
  EMBED_VARIABLE_PATTERN = /\A(\/|\#)\*\$([^\*]+)\*\1\s*/
38
36
 
39
- CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/
40
- BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/
41
- STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string
42
- SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,)
43
- ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/
44
- AND_PATTERN = /\A(\s*AND\s+)/i
45
- OR_PATTERN = /\A(\s*OR\s+)/i
46
- LITERAL_PATTERN = /\A([^;\s]+)/
47
- SPACES_PATTERN = /\A(\s+)/
48
- QUESTION_PATTERN = /\A\?/
49
- COMMA_PATTERN = /\A\,/
50
- LPAREN_PATTERN = /\A\(/
51
- RPAREN_PATTERN = /\A\)/
52
- ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*\s+(.+)\s*\*\1/ ## start with spaces
37
+ CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/
38
+ BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/
39
+ STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string
40
+ SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,)
41
+ LITERAL_PATTERN = /\A([^;\s]+)/
42
+ SPACES_PATTERN = /\A(\s+)/
43
+ QUESTION_PATTERN = /\A\?/
44
+ COMMA_PATTERN = /\A\,/
45
+ LPAREN_PATTERN = /\A\(/
46
+ RPAREN_PATTERN = /\A\)/
47
+ ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*(\s{1,}(?:.*?))\*\1/m ## start with spaces
53
48
  SEMICOLON_AT_INPUT_END_PATTERN = /\A\;\s*\Z/
54
49
  UNMATCHED_COMMENT_START_PATTERN = /\A(?:(?:\/|\#)\*)/
55
50
 
51
+ #TODO: remove trailing spaces for S2Dao compatibility, but this spec sometimes causes SQL bugs...
52
+ ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/
53
+ AND_PATTERN = /\A(\ *AND)\b/i
54
+ OR_PATTERN = /\A(\ *OR)\b/i
55
+
56
56
 
57
57
  def parse( io )
58
58
  @q = []
59
- io.each_line do |line|
60
- s = StringScanner.new(line.rstrip)
59
+ io.each_line(nil) do |whole|
60
+ s = StringScanner.new(whole)
61
61
  until s.eos? do
62
62
  case
63
63
  when s.scan(AND_PATTERN)
@@ -65,7 +65,7 @@ def parse( io )
65
65
  when s.scan(OR_PATTERN)
66
66
  @q.push [ :OR, s[1] ]
67
67
  when s.scan(SPACES_PATTERN)
68
- @q.push [ :SPACES, s[1] ] if @preserve_space
68
+ @q.push [ :SPACES, s[1] ]
69
69
  when s.scan(QUESTION_PATTERN)
70
70
  @q.push [ :QUESTION, nil ]
71
71
  when s.scan(COMMA_PATTERN)
@@ -77,7 +77,7 @@ def parse( io )
77
77
  when s.scan(ELSE_PATTERN)
78
78
  @q.push [ :ELSE, nil ]
79
79
  when s.scan(ACTUAL_COMMENT_PATTERN)
80
- @q.push [ :ACTUAL_COMMENT, s[2] ] if @preserve_comment
80
+ @q.push [ :ACTUAL_COMMENT, [s[1], s[2]] ] if @preserve_comment
81
81
  when s.scan(BEGIN_END_PATTERN)
82
82
  @q.push [ s[2].intern, nil ]
83
83
  when s.scan(CONDITIONAL_PATTERN)
@@ -103,7 +103,6 @@ def parse( io )
103
103
  end
104
104
  end
105
105
 
106
- @q.push [ :EOL, nil ] if @preserve_eol
107
106
  end
108
107
 
109
108
  @q.push [ false, nil ]
@@ -115,109 +114,108 @@ end
115
114
  def next_token
116
115
  @q.shift
117
116
  end
118
- ..end lib/twowaysql/parser.y modeval..id33db4a3791
117
+ ..end lib/twowaysql/parser.y modeval..idd0cee34b5c
119
118
 
120
119
  ##### racc 1.4.5 generates ###
121
120
 
122
121
  racc_reduce_table = [
123
122
  0, 0, :racc_error,
124
- 1, 21, :_reduce_1,
125
- 0, 22, :_reduce_2,
126
- 2, 22, :_reduce_3,
127
- 1, 23, :_reduce_none,
123
+ 1, 20, :_reduce_1,
124
+ 0, 21, :_reduce_2,
125
+ 2, 21, :_reduce_3,
126
+ 1, 22, :_reduce_none,
127
+ 1, 22, :_reduce_none,
128
+ 1, 22, :_reduce_none,
129
+ 3, 25, :_reduce_7,
130
+ 4, 24, :_reduce_8,
131
+ 2, 27, :_reduce_9,
132
+ 0, 27, :_reduce_10,
133
+ 1, 26, :_reduce_none,
134
+ 1, 26, :_reduce_none,
135
+ 1, 26, :_reduce_none,
136
+ 2, 28, :_reduce_14,
137
+ 2, 29, :_reduce_15,
138
+ 1, 23, :_reduce_16,
139
+ 1, 23, :_reduce_17,
140
+ 1, 23, :_reduce_18,
141
+ 1, 23, :_reduce_19,
142
+ 1, 23, :_reduce_20,
143
+ 1, 23, :_reduce_21,
144
+ 1, 23, :_reduce_22,
145
+ 1, 23, :_reduce_23,
146
+ 1, 23, :_reduce_24,
147
+ 1, 23, :_reduce_25,
128
148
  1, 23, :_reduce_none,
129
149
  1, 23, :_reduce_none,
130
- 3, 26, :_reduce_7,
131
- 4, 25, :_reduce_8,
132
- 2, 28, :_reduce_9,
133
- 0, 28, :_reduce_10,
134
- 1, 27, :_reduce_none,
135
- 1, 27, :_reduce_none,
136
- 1, 27, :_reduce_none,
137
- 2, 29, :_reduce_14,
138
- 2, 30, :_reduce_15,
139
- 1, 24, :_reduce_16,
140
- 1, 24, :_reduce_17,
141
- 1, 24, :_reduce_18,
142
- 1, 24, :_reduce_19,
143
- 1, 24, :_reduce_20,
144
- 1, 24, :_reduce_21,
145
- 1, 24, :_reduce_22,
146
- 1, 24, :_reduce_23,
147
- 1, 24, :_reduce_24,
148
- 1, 24, :_reduce_25,
149
- 1, 24, :_reduce_26,
150
- 1, 24, :_reduce_none,
151
- 1, 24, :_reduce_none,
152
- 2, 31, :_reduce_29,
153
- 3, 31, :_reduce_30,
154
- 2, 31, :_reduce_31,
155
- 3, 31, :_reduce_32,
156
- 1, 31, :_reduce_33,
157
- 2, 32, :_reduce_34,
158
- 3, 32, :_reduce_35 ]
159
-
160
- racc_reduce_n = 36
161
-
162
- racc_shift_n = 49
150
+ 2, 30, :_reduce_28,
151
+ 3, 30, :_reduce_29,
152
+ 2, 30, :_reduce_30,
153
+ 3, 30, :_reduce_31,
154
+ 1, 30, :_reduce_32,
155
+ 2, 31, :_reduce_33,
156
+ 3, 31, :_reduce_34 ]
157
+
158
+ racc_reduce_n = 35
159
+
160
+ racc_shift_n = 48
163
161
 
164
162
  racc_action_table = [
165
- 7, 36, 12, 37, 16, 18, 20, 22, 24, 3,
166
- 4, 6, 9, 11, 14, 15, 17, 19, 7, 46,
167
- 12, 40, 16, 18, 20, 22, 24, 3, 4, 6,
168
- 9, 11, 14, 15, 17, 19, 7, 48, 12, 38,
169
- 16, 18, 20, 22, 24, 3, 4, 6, 9, 11,
170
- 14, 15, 17, 19, 7, 39, 12, 25, 16, 18,
171
- 20, 22, 24, 3, 4, 6, 9, 11, 14, 15,
172
- 17, 19, 7, nil, 12, nil, 16, 18, 20, 22,
173
- 24, 3, 4, 6, 9, 11, 14, 15, 17, 19,
174
- 33, 34, 35, 29, 30, 29, 30, 44, 45 ]
163
+ 9, 36, 14, 37, 17, 19, 21, 23, 24, 4,
164
+ 6, 8, 11, 13, 15, 16, 18, 9, 39, 14,
165
+ 45, 17, 19, 21, 23, 24, 4, 6, 8, 11,
166
+ 13, 15, 16, 18, 9, 47, 14, 25, 17, 19,
167
+ 21, 23, 24, 4, 6, 8, 11, 13, 15, 16,
168
+ 18, 9, 38, 14, 3, 17, 19, 21, 23, 24,
169
+ 4, 6, 8, 11, 13, 15, 16, 18, 9, nil,
170
+ 14, nil, 17, 19, 21, 23, 24, 4, 6, 8,
171
+ 11, 13, 15, 16, 18, 33, 34, 35, 28, 30,
172
+ 28, 30, 43, 44 ]
175
173
 
176
174
  racc_action_check = [
177
- 1, 19, 1, 19, 1, 1, 1, 1, 1, 1,
178
- 1, 1, 1, 1, 1, 1, 1, 1, 43, 37,
179
- 43, 28, 43, 43, 43, 43, 43, 43, 43, 43,
180
- 43, 43, 43, 43, 43, 43, 42, 41, 42, 25,
181
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
182
- 42, 42, 42, 42, 26, 26, 26, 2, 26, 26,
183
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
184
- 26, 26, 27, nil, 27, nil, 27, 27, 27, 27,
185
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
186
- 15, 15, 15, 12, 12, 40, 40, 35, 35 ]
175
+ 42, 18, 42, 18, 42, 42, 42, 42, 42, 42,
176
+ 42, 42, 42, 42, 42, 42, 42, 2, 27, 2,
177
+ 37, 2, 2, 2, 2, 2, 2, 2, 2, 2,
178
+ 2, 2, 2, 2, 41, 40, 41, 3, 41, 41,
179
+ 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
180
+ 41, 26, 26, 26, 1, 26, 26, 26, 26, 26,
181
+ 26, 26, 26, 26, 26, 26, 26, 26, 32, nil,
182
+ 32, nil, 32, 32, 32, 32, 32, 32, 32, 32,
183
+ 32, 32, 32, 32, 32, 15, 15, 15, 39, 39,
184
+ 14, 14, 35, 35 ]
187
185
 
188
186
  racc_action_pointer = [
189
- nil, -2, 57, nil, nil, nil, nil, nil, nil, nil,
190
- nil, nil, 87, nil, nil, 82, nil, nil, nil, -7,
191
- nil, nil, nil, nil, nil, 39, 52, 70, 16, nil,
192
- nil, nil, nil, nil, nil, 89, nil, 11, nil, nil,
193
- 89, 34, 34, 16, nil, nil, nil, nil, nil ]
187
+ nil, 54, 15, 37, nil, nil, nil, nil, nil, nil,
188
+ nil, nil, nil, nil, 84, 77, nil, nil, -7, nil,
189
+ nil, nil, nil, nil, nil, nil, 49, 13, nil, nil,
190
+ nil, nil, 66, nil, nil, 84, nil, 12, nil, 82,
191
+ 32, 32, -2, nil, nil, nil, nil, nil ]
194
192
 
195
193
  racc_action_default = [
196
- -2, -1, -36, -21, -22, -3, -23, -2, -4, -24,
197
- -5, -25, -2, -6, -26, -36, -18, -33, -19, -36,
198
- -16, -27, -17, -28, -20, -36, -36, -13, -10, -2,
199
- -2, -11, -12, -31, -29, -36, -34, -36, 49, -7,
200
- -2, -36, -14, -15, -32, -30, -35, -9, -8 ]
194
+ -2, -35, -1, -35, -21, -3, -22, -4, -23, -2,
195
+ -5, -24, -6, -25, -2, -35, -32, -18, -35, -19,
196
+ -26, -16, -27, -17, -20, 48, -35, -10, -2, -11,
197
+ -2, -12, -13, -30, -28, -35, -33, -35, -7, -2,
198
+ -35, -14, -15, -31, -29, -34, -9, -8 ]
201
199
 
202
200
  racc_goto_table = [
203
- 1, 2, 41, 28, nil, nil, nil, 26, nil, nil,
201
+ 2, 27, 1, 40, nil, nil, nil, nil, nil, 26,
204
202
  nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
205
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 42,
206
- 43, 47 ]
203
+ nil, nil, nil, nil, nil, nil, 46, nil, 41, nil,
204
+ 42 ]
207
205
 
208
206
  racc_goto_check = [
209
- 2, 1, 8, 7, nil, nil, nil, 2, nil, nil,
207
+ 2, 7, 1, 8, nil, nil, nil, nil, nil, 2,
210
208
  nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
211
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 2,
212
- 2, 7 ]
209
+ nil, nil, nil, nil, nil, nil, 7, nil, 2, nil,
210
+ 2 ]
213
211
 
214
212
  racc_goto_pointer = [
215
- nil, 1, 0, nil, nil, nil, nil, -9, -26, nil,
213
+ nil, 2, 0, nil, nil, nil, nil, -13, -24, nil,
216
214
  nil, nil, nil ]
217
215
 
218
216
  racc_goto_default = [
219
- nil, nil, 27, 5, 8, 10, 13, nil, nil, 31,
220
- 32, 21, 23 ]
217
+ nil, nil, 32, 5, 7, 10, 12, nil, nil, 29,
218
+ 31, 20, 22 ]
221
219
 
222
220
  racc_token_table = {
223
221
  false => 0,
@@ -236,14 +234,13 @@ racc_token_table = {
236
234
  :RPAREN => 13,
237
235
  :QUESTION => 14,
238
236
  :ACTUAL_COMMENT => 15,
239
- :EOL => 16,
240
- :BIND_VARIABLE => 17,
241
- :PAREN_BIND_VARIABLE => 18,
242
- :EMBED_VARIABLE => 19 }
237
+ :BIND_VARIABLE => 16,
238
+ :PAREN_BIND_VARIABLE => 17,
239
+ :EMBED_VARIABLE => 18 }
243
240
 
244
241
  racc_use_result_var = true
245
242
 
246
- racc_nt_base = 20
243
+ racc_nt_base = 19
247
244
 
248
245
  Racc_arg = [
249
246
  racc_action_table,
@@ -278,7 +275,6 @@ Racc_token_to_s_table = [
278
275
  'RPAREN',
279
276
  'QUESTION',
280
277
  'ACTUAL_COMMENT',
281
- 'EOL',
282
278
  'BIND_VARIABLE',
283
279
  'PAREN_BIND_VARIABLE',
284
280
  'EMBED_VARIABLE',
@@ -407,7 +403,7 @@ module_eval <<'.,.,', 'lib/twowaysql/parser.y', 71
407
403
 
408
404
  module_eval <<'.,.,', 'lib/twowaysql/parser.y', 75
409
405
  def _reduce_20( val, _values, result )
410
- result = LiteralNode.new( val[0] )
406
+ result = WhiteSpaceNode.new( val[0], @preserve_space )
411
407
  result
412
408
  end
413
409
  .,.,
@@ -443,21 +439,21 @@ module_eval <<'.,.,', 'lib/twowaysql/parser.y', 92
443
439
 
444
440
  module_eval <<'.,.,', 'lib/twowaysql/parser.y', 96
445
441
  def _reduce_25( val, _values, result )
446
- result = CommentNode.new( val[0] )
442
+ result = ActualCommentNode.new( val[0][0] , val[0][1] )
447
443
  result
448
444
  end
449
445
  .,.,
450
446
 
451
- module_eval <<'.,.,', 'lib/twowaysql/parser.y', 100
452
- def _reduce_26( val, _values, result )
453
- result = EolNode.new
454
- result
455
- end
456
- .,.,
447
+ # reduce 26 omitted
457
448
 
458
449
  # reduce 27 omitted
459
450
 
460
- # reduce 28 omitted
451
+ module_eval <<'.,.,', 'lib/twowaysql/parser.y', 103
452
+ def _reduce_28( val, _values, result )
453
+ result = BindVariableNode.new( val[0] )
454
+ result
455
+ end
456
+ .,.,
461
457
 
462
458
  module_eval <<'.,.,', 'lib/twowaysql/parser.y', 107
463
459
  def _reduce_29( val, _values, result )
@@ -482,14 +478,14 @@ module_eval <<'.,.,', 'lib/twowaysql/parser.y', 115
482
478
 
483
479
  module_eval <<'.,.,', 'lib/twowaysql/parser.y', 119
484
480
  def _reduce_32( val, _values, result )
485
- result = BindVariableNode.new( val[0] )
481
+ result = ParenBindVariableNode.new( val[0] )
486
482
  result
487
483
  end
488
484
  .,.,
489
485
 
490
- module_eval <<'.,.,', 'lib/twowaysql/parser.y', 123
486
+ module_eval <<'.,.,', 'lib/twowaysql/parser.y', 124
491
487
  def _reduce_33( val, _values, result )
492
- result = ParenBindVariableNode.new( val[0] )
488
+ result = EmbedVariableNode.new( val[0] )
493
489
  result
494
490
  end
495
491
  .,.,
@@ -501,13 +497,6 @@ module_eval <<'.,.,', 'lib/twowaysql/parser.y', 128
501
497
  end
502
498
  .,.,
503
499
 
504
- module_eval <<'.,.,', 'lib/twowaysql/parser.y', 132
505
- def _reduce_35( val, _values, result )
506
- result = EmbedVariableNode.new( val[0] )
507
- result
508
- end
509
- .,.,
510
-
511
500
  def _reduce_none( val, _values, result )
512
501
  result
513
502
  end
@@ -71,7 +71,7 @@ primary : IDENT
71
71
  }
72
72
  | SPACES
73
73
  {
74
- result = LiteralNode.new( val[0] )
74
+ result = WhiteSpaceNode.new( val[0], @preserve_space )
75
75
  }
76
76
  | COMMA
77
77
  {
@@ -92,11 +92,7 @@ primary : IDENT
92
92
  }
93
93
  | ACTUAL_COMMENT
94
94
  {
95
- result = CommentNode.new( val[0] )
96
- }
97
- | EOL
98
- {
99
- result = EolNode.new
95
+ result = ActualCommentNode.new( val[0][0] , val[0][1] )
100
96
  }
101
97
  | bind_var
102
98
  | embed_var
@@ -140,15 +136,13 @@ require 'strscan'
140
136
 
141
137
  def initialize(opts={})
142
138
  opts = {
143
- :debug => true,
139
+ :debug => false,
144
140
  :preserve_space => true,
145
- :preserve_comment => true,
146
- :preserve_eol => true
141
+ :preserve_comment => false
147
142
  }.merge(opts)
148
143
  @yydebug = opts[:debug]
149
144
  @preserve_space = opts[:preserve_space]
150
145
  @preserve_comment = opts[:preserve_comment]
151
- @preserve_eol = opts[:preserve_eol]
152
146
  @num_questions = 0
153
147
  end
154
148
 
@@ -159,28 +153,30 @@ BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*/
159
153
  PAREN_BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*#{PAREN_EXAMPLE}/
160
154
  EMBED_VARIABLE_PATTERN = /\A(\/|\#)\*\$([^\*]+)\*\1\s*/
161
155
 
162
- CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/
163
- BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/
164
- STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string
165
- SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,)
166
- ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/
167
- AND_PATTERN = /\A(\s*AND\s+)/i
168
- OR_PATTERN = /\A(\s*OR\s+)/i
169
- LITERAL_PATTERN = /\A([^;\s]+)/
170
- SPACES_PATTERN = /\A(\s+)/
171
- QUESTION_PATTERN = /\A\?/
172
- COMMA_PATTERN = /\A\,/
173
- LPAREN_PATTERN = /\A\(/
174
- RPAREN_PATTERN = /\A\)/
175
- ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*\s+(.+)\s*\*\1/ ## start with spaces
156
+ CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/
157
+ BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/
158
+ STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string
159
+ SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,)
160
+ LITERAL_PATTERN = /\A([^;\s]+)/
161
+ SPACES_PATTERN = /\A(\s+)/
162
+ QUESTION_PATTERN = /\A\?/
163
+ COMMA_PATTERN = /\A\,/
164
+ LPAREN_PATTERN = /\A\(/
165
+ RPAREN_PATTERN = /\A\)/
166
+ ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*(\s{1,}(?:.*?))\*\1/m ## start with spaces
176
167
  SEMICOLON_AT_INPUT_END_PATTERN = /\A\;\s*\Z/
177
168
  UNMATCHED_COMMENT_START_PATTERN = /\A(?:(?:\/|\#)\*)/
178
169
 
170
+ #TODO: remove trailing spaces for S2Dao compatibility, but this spec sometimes causes SQL bugs...
171
+ ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/
172
+ AND_PATTERN = /\A(\ *AND)\b/i
173
+ OR_PATTERN = /\A(\ *OR)\b/i
174
+
179
175
 
180
176
  def parse( io )
181
177
  @q = []
182
- io.each_line do |line|
183
- s = StringScanner.new(line.rstrip)
178
+ io.each_line(nil) do |whole|
179
+ s = StringScanner.new(whole)
184
180
  until s.eos? do
185
181
  case
186
182
  when s.scan(AND_PATTERN)
@@ -188,7 +184,7 @@ def parse( io )
188
184
  when s.scan(OR_PATTERN)
189
185
  @q.push [ :OR, s[1] ]
190
186
  when s.scan(SPACES_PATTERN)
191
- @q.push [ :SPACES, s[1] ] if @preserve_space
187
+ @q.push [ :SPACES, s[1] ]
192
188
  when s.scan(QUESTION_PATTERN)
193
189
  @q.push [ :QUESTION, nil ]
194
190
  when s.scan(COMMA_PATTERN)
@@ -200,7 +196,7 @@ def parse( io )
200
196
  when s.scan(ELSE_PATTERN)
201
197
  @q.push [ :ELSE, nil ]
202
198
  when s.scan(ACTUAL_COMMENT_PATTERN)
203
- @q.push [ :ACTUAL_COMMENT, s[2] ] if @preserve_comment
199
+ @q.push [ :ACTUAL_COMMENT, [s[1], s[2]] ] if @preserve_comment
204
200
  when s.scan(BEGIN_END_PATTERN)
205
201
  @q.push [ s[2].intern, nil ]
206
202
  when s.scan(CONDITIONAL_PATTERN)
@@ -226,7 +222,6 @@ def parse( io )
226
222
  end
227
223
  end
228
224
 
229
- @q.push [ :EOL, nil ] if @preserve_eol
230
225
  end
231
226
 
232
227
  @q.push [ false, nil ]
@@ -1,5 +1,3 @@
1
- require 'forwardable'
2
-
3
1
  module TwoWaySQL
4
2
 
5
3
  # TwoWaySQL::Template represents template object, acts as a Facade for this package.
@@ -64,12 +62,36 @@ module TwoWaySQL
64
62
 
65
63
  # TwoWaySQL::Result represents merge result of template and data.
66
64
  # it contains SQL string with placeholders, and bound variables associated with placeholders.
65
+ #
66
+ # === Usage
67
+ #
68
+ # merged = template.merge(:job => "HOGE", :deptno => 30)
69
+ # merged.sql #=> "SELECT * FROM emp WHERE job = ? AND deptno = ?"
70
+ # merged.bound_variables #=> ["HOGE", 30]
71
+ #
67
72
  class Result
68
- extend Forwardable
69
73
  def initialize(context)
70
74
  @context = context
71
75
  end
72
- def_delegators :@context, :sql, :bound_variables
76
+
77
+ # return merge result SQL with placeholders (question mark).
78
+ #
79
+ # === Return
80
+ # merge result SQL with placeholders
81
+ #
82
+ def sql
83
+ @context.sql
84
+ end
85
+
86
+ # return array of variables which indices are corresponding to placeholders.
87
+ #
88
+ # === Return
89
+ # merge result SQL with placeholders
90
+ #
91
+ def bound_variables
92
+ @context.bound_variables
93
+ end
94
+ alias vars bound_variables
73
95
  end
74
96
 
75
97
  end
@@ -1,8 +1,8 @@
1
1
  module TwoWaySQL
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 2
5
- TINY = 1
4
+ MINOR = 3
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -153,11 +153,26 @@ from
153
153
  /*IF ctx[:id_list] */and id in /*ctx[:id_list]*/(3, 4, 9)/*END*/
154
154
  /*END*/
155
155
  EOS
156
- template = TwoWaySQL::Template.parse(sql)
157
- @result = template.merge(:id_list => [10, 11])
156
+ @template = TwoWaySQL::Template.parse(sql)
158
157
  end
159
158
 
160
- it "sql" do
159
+ it "if both line is true" do
160
+ expected = <<-EOS
161
+ select
162
+ *
163
+ from
164
+ hoge
165
+ where
166
+ name like ?
167
+ and id in (?, ?)
168
+
169
+ EOS
170
+ @result = @template.merge(:name => 'foo%', :id_list => [10, 11])
171
+ @result.sql.should == expected
172
+ @result.bound_variables.should == ['foo%', 10, 11]
173
+ end
174
+
175
+ it "if second line is true" do
161
176
  expected = <<-EOS
162
177
  select
163
178
  *
@@ -165,12 +180,60 @@ from
165
180
  hoge
166
181
  where
167
182
 
168
- id in (?, ?)
183
+ id in (?, ?)
169
184
 
170
185
  EOS
186
+ @result = @template.merge(:id_list => [10, 11])
171
187
  @result.sql.should == expected
172
188
  @result.bound_variables.should == [10, 11]
173
189
  end
190
+
191
+ end
192
+
193
+
194
+
195
+
196
+ describe "examples in website" do
197
+ it do
198
+ # given SQL string with TwoWaySQL comments
199
+ sql = <<-EOS
200
+ SELECT * FROM emp
201
+ /*BEGIN*/WHERE
202
+ /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK' /*END*/
203
+ /*IF ctx[:deptno_list]*/ AND deptno IN /*ctx[:deptno_list]*/(20, 30) /*END*/
204
+ /*IF ctx[:age]*/ AND age > /*ctx[:age]*/30 /*END*/
205
+ /*END*/
206
+ /*IF ctx[:order_by] */ ORDER BY /*$ctx[:order_by]*/id /*$ctx[:order]*/ASC /*END*/
207
+ EOS
208
+
209
+
210
+ # parse the SQL to create template object
211
+ template = TwoWaySQL::Template.parse(sql)
212
+
213
+
214
+ # merge data with template
215
+ data = {
216
+ :age => 35,
217
+ :deptno_list => [10,20,30],
218
+ :order_by => 'age',
219
+ :order => 'DESC'
220
+ }
221
+ merged = template.merge(data)
222
+
223
+
224
+ expected_sql = <<-EOS
225
+ SELECT * FROM emp
226
+ WHERE
227
+
228
+ deptno IN (?, ?, ?)
229
+ AND age > ?
230
+
231
+ ORDER BY age DESC
232
+ EOS
233
+
234
+ merged.sql.should == expected_sql #=> true
235
+ merged.bound_variables.should == [10,20,30,35]
236
+ end
174
237
  end
175
238
 
176
239
  end