sql_search_parser 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 66866005a717ecfd956c7e12def19dd1bf84d1ce
4
+ data.tar.gz: 6a234f90d1ffd9ebe1a3fadb405327116f69dd90
5
+ SHA512:
6
+ metadata.gz: d1e18ffd9a85b75be8d76d26e1f191c5d7eef31f9de446987b586d01b9333718b22149f5f44693961a4ad0bfa06a4212643a6b9c6894771e7b6b4b44f3a87727
7
+ data.tar.gz: 56de07980807906da360b056fb6784e9ef4e76368f1b2a45952e4084794def05926b27ee92ab31ee504d550210a87ee6eb4f85510b0841b2a06423136fbf7078
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 NIEK Antoine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,50 @@
1
+ sql_search_parser
2
+ =================
3
+
4
+ Simple SQL search conditions parser (where clause) based on RACC
5
+
6
+ Usage
7
+ -----
8
+ SQLSearch::Parser.new.parse("a = 2")
9
+ => #<SQLSearch::Comparison:0x00000000fd12e0 @left=#<SQLSearch::Atoms::Column:0x00000000fd1588 @name="a", @table=nil, @space=nil>, @right=#<SQLSearch::Atoms::Literal:0x00000000fd1380 @value=2, @type=:int>, @operator=:"=">
10
+
11
+ SQLSearch::Parser.new.parse("a = 2 and b = 3").to_s
12
+ => "(`a` = 2) AND (`b` = 3)"
13
+
14
+ SQLSearch::Parser.new.parse("b = '2013-01-01T00:00:00Z'").right.value
15
+ => #<DateTime: 2013-01-01T00:00:00+00:00 ((2456294j,0s,0n),+0s,2299161j)>
16
+
17
+ SQLSearch::Parser.new.parse("b = '2013-01-01T00:00:00-05:00'").right.value
18
+ => #<DateTime: 2013-01-01T00:00:00-05:00 ((2456294j,18000s,0n),-18000s,2299161j)>
19
+
20
+ SQLSearch::Parser.new.parse("b IN(1,2,3)").right.values.map(&:value)
21
+ => [1, 2, 3]
22
+
23
+ SQLSearch::Parser.new.parse("b + 1 > c").left
24
+ => #<SQLSearch::Atoms::Scalar:0x000000016ceef8 @left=#<SQLSearch::Atoms::Column:0x000000016cf308 @name="b", @table=nil, @space=nil>, @right=#<SQLSearch::Atoms::Literal:0x000000016cf100 @value=1, @type=:int>, @operation=:+>
25
+
26
+ For more examples look at the tests :)
27
+
28
+ Installation
29
+ ------------
30
+ gem install sql_search_parser
31
+
32
+ or add in your Gemfile
33
+
34
+ gem 'sql_search_parser'
35
+
36
+ Build Dependencies
37
+ ------------------
38
+ rake, rexical, racc
39
+
40
+ Build & install Gem locally
41
+ -----
42
+ rake package
43
+
44
+ Run the tests
45
+ -----
46
+ rake
47
+
48
+ or
49
+
50
+ rake test
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require_relative 'lib/sql_search/version'
2
+ require 'rake/testtask'
3
+
4
+ desc "Generate Lexer"
5
+
6
+ task :lexer do
7
+ `rex lib/sql_search/parser.rex -o lib/sql_search/parser.rex.rb`
8
+ end
9
+
10
+ task :parser do
11
+ `racc lib/sql_search/parser.y -o lib/sql_search/parser.racc.rb`
12
+ end
13
+
14
+ task :build => [:lexer, :parser]
15
+
16
+ task :package => [:build] do
17
+ `gem build sql_search_parser.gemspec`
18
+ `gem install sql_search_parser-#{SQLSearch::VERSION}.gem`
19
+ end
20
+
21
+ Rake::TestTask.new do |t|
22
+ t.pattern = "test/**/*_test.rb"
23
+ end
24
+
25
+ task :default => [:test]
26
+
@@ -0,0 +1,485 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.11
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require 'date'
10
+ require_relative 'parser.rex.rb'
11
+
12
+ module SQLSearch
13
+ class Parser < Racc::Parser
14
+
15
+ module_eval(<<'...end parser.y/module_eval...', 'parser.y', 94)
16
+ def parse(input)
17
+ scan_str(input)
18
+ end
19
+ ...end parser.y/module_eval...
20
+ ##### State transition tables begin ###
21
+
22
+ racc_action_table = [
23
+ 2, 3, 48, 49, 53, 58, 77, 50, 64, 2,
24
+ 3, 12, 13, 59, 78, 16, 17, 18, 19, 20,
25
+ 12, 13, 2, 3, 16, 17, 18, 19, 20, 22,
26
+ 23, 2, 3, 12, 13, 22, 23, 16, 17, 18,
27
+ 19, 20, 12, 13, 2, 3, 16, 17, 18, 19,
28
+ 20, 22, 23, 70, 39, 12, 13, 67, 67, 16,
29
+ 17, 18, 19, 20, 12, 13, 39, 79, 16, 17,
30
+ 18, 19, 20, 71, 42, 39, 12, 13, 41, 36,
31
+ 16, 17, 18, 19, 20, 12, 13, 39, 61, 16,
32
+ 17, 18, 19, 20, nil, nil, 39, 12, 13, nil,
33
+ nil, 16, 17, 18, 19, 20, 12, 13, 39, nil,
34
+ 16, 17, 18, 19, 20, nil, nil, 39, 12, 13,
35
+ nil, nil, 16, 17, 18, 19, 20, 12, 13, 39,
36
+ nil, 16, 17, 18, 19, 20, nil, nil, 39, 12,
37
+ 13, nil, nil, 16, 17, 18, 19, 20, 12, 13,
38
+ 39, nil, 16, 17, 18, 19, 20, nil, nil, 39,
39
+ 12, 13, nil, nil, 16, 17, 18, 19, 20, 12,
40
+ 13, 39, 81, 16, 17, 18, 19, 20, 65, nil,
41
+ 78, 12, 13, 72, nil, 16, 17, 18, 19, 20,
42
+ 32, 33, 34, 35, nil, 32, 33, 34, 35, 28,
43
+ nil, nil, 27, 29, 30, 22, 23, nil, 31, 45,
44
+ 32, 33, 34, 35, 28, nil, 46, 27, 29, 30,
45
+ 46, nil, nil, 31, nil, 32, 33, 34, 35, 32,
46
+ 33, 34, 35, 16, 17, 18, 19, 16, 17, 18,
47
+ 19, 32, 33, 34, 35, 32, 33, 34, 35, 32,
48
+ 33, 34, 35, 21, nil, 22, 23, 16, 17, 18,
49
+ 19, 16, 17, 18, 19, 32, 33, 34, 35, 16,
50
+ 17, 18, 19, 16, 17, 18, 19, 32, 33, 34,
51
+ 35, 32, 33, 34, 35, 32, 33, 34, 35, 32,
52
+ 33, 34, 35, 32, 33, 34, 35 ]
53
+
54
+ racc_action_check = [
55
+ 0, 0, 28, 28, 31, 36, 68, 28, 50, 23,
56
+ 23, 0, 0, 36, 68, 0, 0, 0, 0, 0,
57
+ 23, 23, 2, 2, 23, 23, 23, 23, 23, 44,
58
+ 44, 3, 3, 2, 2, 24, 24, 2, 2, 2,
59
+ 2, 2, 3, 3, 22, 22, 3, 3, 3, 3,
60
+ 3, 43, 43, 58, 35, 22, 22, 52, 63, 22,
61
+ 22, 22, 22, 22, 35, 35, 12, 71, 35, 35,
62
+ 35, 35, 35, 61, 21, 13, 12, 12, 20, 11,
63
+ 12, 12, 12, 12, 12, 13, 13, 39, 41, 13,
64
+ 13, 13, 13, 13, nil, nil, 34, 39, 39, nil,
65
+ nil, 39, 39, 39, 39, 39, 34, 34, 65, nil,
66
+ 34, 34, 34, 34, 34, nil, nil, 48, 65, 65,
67
+ nil, nil, 65, 65, 65, 65, 65, 48, 48, 72,
68
+ nil, 48, 48, 48, 48, 48, nil, nil, 29, 72,
69
+ 72, nil, nil, 72, 72, 72, 72, 72, 29, 29,
70
+ 32, nil, 29, 29, 29, 29, 29, nil, nil, 27,
71
+ 32, 32, nil, nil, 32, 32, 32, 32, 32, 27,
72
+ 27, 33, 74, 27, 27, 27, 27, 27, 51, nil,
73
+ 74, 33, 33, 62, nil, 33, 33, 33, 33, 33,
74
+ 51, 51, 51, 51, nil, 62, 62, 62, 62, 10,
75
+ nil, nil, 10, 10, 10, 25, 25, nil, 10, 25,
76
+ 10, 10, 10, 10, 26, nil, 26, 26, 26, 26,
77
+ 60, nil, nil, 26, nil, 26, 26, 26, 26, 60,
78
+ 60, 60, 60, 67, 67, 67, 67, 78, 78, 78,
79
+ 78, 40, 40, 40, 40, 37, 37, 37, 37, 47,
80
+ 47, 47, 47, 1, nil, 1, 1, 49, 49, 49,
81
+ 49, 64, 64, 64, 64, 75, 75, 75, 75, 30,
82
+ 30, 30, 30, 53, 53, 53, 53, 54, 54, 54,
83
+ 54, 55, 55, 55, 55, 56, 56, 56, 56, 57,
84
+ 57, 57, 57, 80, 80, 80, 80 ]
85
+
86
+ racc_action_pointer = [
87
+ -4, 253, 18, 27, nil, nil, nil, nil, nil, nil,
88
+ 195, 68, 61, 70, nil, nil, nil, nil, nil, nil,
89
+ 54, 74, 40, 5, 33, 203, 210, 154, -6, 133,
90
+ 250, -1, 145, 166, 91, 49, 1, 230, nil, 82,
91
+ 226, 65, nil, 49, 27, nil, nil, 234, 112, 238,
92
+ 3, 175, 47, 254, 262, 266, 270, 274, 41, nil,
93
+ 214, 49, 180, 48, 242, 103, nil, 214, 0, nil,
94
+ nil, 44, 124, nil, 166, 250, nil, nil, 218, nil,
95
+ 278, nil, nil ]
96
+
97
+ racc_action_default = [
98
+ -41, -41, -41, -41, -5, -6, -7, -8, -9, -10,
99
+ -41, -31, -41, -41, -30, -33, -34, -35, -36, -37,
100
+ -38, -41, -41, -41, -3, -41, -41, -41, -41, -41,
101
+ -41, -41, -41, -41, -41, -41, -41, -28, -31, -41,
102
+ -29, -41, 83, -1, -2, -4, -32, -11, -41, -41,
103
+ -41, -41, -16, -41, -24, -25, -26, -27, -41, -19,
104
+ -41, -39, -41, -16, -41, -41, -15, -41, -41, -22,
105
+ -18, -41, -41, -14, -41, -13, -17, -21, -41, -40,
106
+ -12, -20, -23 ]
107
+
108
+ racc_goto_table = [
109
+ 26, 66, nil, nil, 52, 68, nil, nil, nil, 37,
110
+ 40, 1, 73, 24, 25, nil, 74, 11, nil, 11,
111
+ 11, nil, nil, 63, 47, nil, 51, 69, nil, 54,
112
+ 55, 56, 57, 43, 44, nil, 60, nil, 69, 11,
113
+ 11, 76, nil, nil, nil, 62, nil, nil, nil, nil,
114
+ nil, nil, 82, nil, nil, nil, nil, nil, nil, nil,
115
+ nil, nil, 75, nil, nil, nil, nil, nil, nil, 80 ]
116
+
117
+ racc_goto_check = [
118
+ 8, 10, nil, nil, 9, 12, nil, nil, nil, 8,
119
+ 8, 1, 10, 1, 1, nil, 12, 11, nil, 11,
120
+ 11, nil, nil, 9, 8, nil, 8, 9, nil, 8,
121
+ 8, 8, 8, 1, 1, nil, 8, nil, 9, 11,
122
+ 11, 9, nil, nil, nil, 8, nil, nil, nil, nil,
123
+ nil, nil, 9, nil, nil, nil, nil, nil, nil, nil,
124
+ nil, nil, 8, nil, nil, nil, nil, nil, nil, 8 ]
125
+
126
+ racc_goto_pointer = [
127
+ nil, 11, nil, nil, nil, nil, nil, nil, -3, -26,
128
+ -51, 17, -48, nil ]
129
+
130
+ racc_goto_default = [
131
+ nil, nil, 4, 5, 6, 7, 8, 9, 10, 14,
132
+ nil, 38, nil, 15 ]
133
+
134
+ racc_reduce_table = [
135
+ 0, 0, :racc_error,
136
+ 3, 26, :_reduce_1,
137
+ 3, 26, :_reduce_2,
138
+ 2, 26, :_reduce_3,
139
+ 3, 26, :_reduce_none,
140
+ 1, 26, :_reduce_none,
141
+ 1, 27, :_reduce_none,
142
+ 1, 27, :_reduce_none,
143
+ 1, 27, :_reduce_none,
144
+ 1, 27, :_reduce_none,
145
+ 1, 27, :_reduce_none,
146
+ 3, 28, :_reduce_11,
147
+ 6, 29, :_reduce_none,
148
+ 5, 29, :_reduce_none,
149
+ 5, 30, :_reduce_14,
150
+ 4, 30, :_reduce_15,
151
+ 0, 35, :_reduce_none,
152
+ 2, 35, :_reduce_none,
153
+ 4, 31, :_reduce_18,
154
+ 3, 31, :_reduce_19,
155
+ 6, 32, :_reduce_20,
156
+ 5, 32, :_reduce_21,
157
+ 1, 37, :_reduce_22,
158
+ 3, 37, :_reduce_23,
159
+ 3, 33, :_reduce_24,
160
+ 3, 33, :_reduce_25,
161
+ 3, 33, :_reduce_26,
162
+ 3, 33, :_reduce_27,
163
+ 2, 33, :_reduce_28,
164
+ 2, 33, :_reduce_29,
165
+ 1, 33, :_reduce_none,
166
+ 1, 33, :_reduce_none,
167
+ 3, 33, :_reduce_none,
168
+ 1, 34, :_reduce_none,
169
+ 1, 38, :_reduce_34,
170
+ 1, 38, :_reduce_35,
171
+ 1, 38, :_reduce_36,
172
+ 1, 38, :_reduce_37,
173
+ 1, 36, :_reduce_38,
174
+ 3, 36, :_reduce_39,
175
+ 5, 36, :_reduce_40 ]
176
+
177
+ racc_reduce_n = 41
178
+
179
+ racc_shift_n = 83
180
+
181
+ racc_token_table = {
182
+ false => 0,
183
+ :error => 1,
184
+ :OR => 2,
185
+ :AND => 3,
186
+ :NOT => 4,
187
+ :LPAREN => 5,
188
+ :RPAREN => 6,
189
+ :COMPARISON => 7,
190
+ :BETWEEN => 8,
191
+ :LIKE => 9,
192
+ :ESCAPE => 10,
193
+ :IS => 11,
194
+ :NULL => 12,
195
+ :IN => 13,
196
+ :COMMA => 14,
197
+ :ADD => 15,
198
+ :SUBTRACT => 16,
199
+ :MULTIPLY => 17,
200
+ :DIVIDE => 18,
201
+ :STRING => 19,
202
+ :APPROXNUM => 20,
203
+ :INTNUM => 21,
204
+ :TIME => 22,
205
+ :NAME => 23,
206
+ :DOT => 24 }
207
+
208
+ racc_nt_base = 25
209
+
210
+ racc_use_result_var = true
211
+
212
+ Racc_arg = [
213
+ racc_action_table,
214
+ racc_action_check,
215
+ racc_action_default,
216
+ racc_action_pointer,
217
+ racc_goto_table,
218
+ racc_goto_check,
219
+ racc_goto_default,
220
+ racc_goto_pointer,
221
+ racc_nt_base,
222
+ racc_reduce_table,
223
+ racc_token_table,
224
+ racc_shift_n,
225
+ racc_reduce_n,
226
+ racc_use_result_var ]
227
+
228
+ Racc_token_to_s_table = [
229
+ "$end",
230
+ "error",
231
+ "OR",
232
+ "AND",
233
+ "NOT",
234
+ "LPAREN",
235
+ "RPAREN",
236
+ "COMPARISON",
237
+ "BETWEEN",
238
+ "LIKE",
239
+ "ESCAPE",
240
+ "IS",
241
+ "NULL",
242
+ "IN",
243
+ "COMMA",
244
+ "ADD",
245
+ "SUBTRACT",
246
+ "MULTIPLY",
247
+ "DIVIDE",
248
+ "STRING",
249
+ "APPROXNUM",
250
+ "INTNUM",
251
+ "TIME",
252
+ "NAME",
253
+ "DOT",
254
+ "$start",
255
+ "search_condition",
256
+ "predicate",
257
+ "comparison_predicate",
258
+ "between_predicate",
259
+ "like_predicate",
260
+ "test_for_null",
261
+ "in_predicate",
262
+ "scalar_exp",
263
+ "atom",
264
+ "opt_escape",
265
+ "column_ref",
266
+ "atom_commalist",
267
+ "literal" ]
268
+
269
+ Racc_debug_parser = false
270
+
271
+ ##### State transition tables end #####
272
+
273
+ # reduce 0 omitted
274
+
275
+ module_eval(<<'.,.,', 'parser.y', 6)
276
+ def _reduce_1(val, _values, result)
277
+ result = Conditions::Or.new(:left => val[0], :right => val[2])
278
+ result
279
+ end
280
+ .,.,
281
+
282
+ module_eval(<<'.,.,', 'parser.y', 7)
283
+ def _reduce_2(val, _values, result)
284
+ result = Conditions::And.new(:left => val[0], :right => val[2])
285
+ result
286
+ end
287
+ .,.,
288
+
289
+ module_eval(<<'.,.,', 'parser.y', 8)
290
+ def _reduce_3(val, _values, result)
291
+ result = Conditions::Not.new(:value => val[1])
292
+ result
293
+ end
294
+ .,.,
295
+
296
+ # reduce 4 omitted
297
+
298
+ # reduce 5 omitted
299
+
300
+ # reduce 6 omitted
301
+
302
+ # reduce 7 omitted
303
+
304
+ # reduce 8 omitted
305
+
306
+ # reduce 9 omitted
307
+
308
+ # reduce 10 omitted
309
+
310
+ module_eval(<<'.,.,', 'parser.y', 22)
311
+ def _reduce_11(val, _values, result)
312
+ result = Comparison.new(:left => val[0], :right => val[2], :operator => val[1].to_sym)
313
+ result
314
+ end
315
+ .,.,
316
+
317
+ # reduce 12 omitted
318
+
319
+ # reduce 13 omitted
320
+
321
+ module_eval(<<'.,.,', 'parser.y', 31)
322
+ def _reduce_14(val, _values, result)
323
+ result = Conditions::Not.new(:value => Comparison.new(:left => val[0], :right => val[3], :operator => :LIKE))
324
+ result
325
+ end
326
+ .,.,
327
+
328
+ module_eval(<<'.,.,', 'parser.y', 32)
329
+ def _reduce_15(val, _values, result)
330
+ result = Comparison.new(:left => val[0], :right => val[2], :operator => :LIKE)
331
+ result
332
+ end
333
+ .,.,
334
+
335
+ # reduce 16 omitted
336
+
337
+ # reduce 17 omitted
338
+
339
+ module_eval(<<'.,.,', 'parser.y', 41)
340
+ def _reduce_18(val, _values, result)
341
+ result = Comparison.new(:left => val[0], :right => val[3], :operator => :'<>')
342
+ result
343
+ end
344
+ .,.,
345
+
346
+ module_eval(<<'.,.,', 'parser.y', 42)
347
+ def _reduce_19(val, _values, result)
348
+ result = Comparison.new(:left => val[0], :right => val[2], :operator => :'=')
349
+ result
350
+ end
351
+ .,.,
352
+
353
+ module_eval(<<'.,.,', 'parser.y', 46)
354
+ def _reduce_20(val, _values, result)
355
+ result = Conditions::Not.new(:value => In.new(:left => val[0], :right => Atoms::InValues.new(:values => val[4])))
356
+ result
357
+ end
358
+ .,.,
359
+
360
+ module_eval(<<'.,.,', 'parser.y', 47)
361
+ def _reduce_21(val, _values, result)
362
+ result = In.new(:left => val[0], :right => Atoms::InValues.new(:values => val[3]))
363
+ result
364
+ end
365
+ .,.,
366
+
367
+ module_eval(<<'.,.,', 'parser.y', 51)
368
+ def _reduce_22(val, _values, result)
369
+ result = [val[0]]
370
+ result
371
+ end
372
+ .,.,
373
+
374
+ module_eval(<<'.,.,', 'parser.y', 52)
375
+ def _reduce_23(val, _values, result)
376
+ result = val[0].concat([val[2]])
377
+ result
378
+ end
379
+ .,.,
380
+
381
+ module_eval(<<'.,.,', 'parser.y', 58)
382
+ def _reduce_24(val, _values, result)
383
+ result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'+')
384
+ result
385
+ end
386
+ .,.,
387
+
388
+ module_eval(<<'.,.,', 'parser.y', 59)
389
+ def _reduce_25(val, _values, result)
390
+ result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'-')
391
+ result
392
+ end
393
+ .,.,
394
+
395
+ module_eval(<<'.,.,', 'parser.y', 60)
396
+ def _reduce_26(val, _values, result)
397
+ result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'*')
398
+ result
399
+ end
400
+ .,.,
401
+
402
+ module_eval(<<'.,.,', 'parser.y', 61)
403
+ def _reduce_27(val, _values, result)
404
+ result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'/')
405
+ result
406
+ end
407
+ .,.,
408
+
409
+ module_eval(<<'.,.,', 'parser.y', 62)
410
+ def _reduce_28(val, _values, result)
411
+ result = Atoms::UnaryScalar.new(:value => val[1], :operation => :'+')
412
+ result
413
+ end
414
+ .,.,
415
+
416
+ module_eval(<<'.,.,', 'parser.y', 63)
417
+ def _reduce_29(val, _values, result)
418
+ result = Atoms::UnaryScalar.new(:value => val[1], :operation => :'-')
419
+ result
420
+ end
421
+ .,.,
422
+
423
+ # reduce 30 omitted
424
+
425
+ # reduce 31 omitted
426
+
427
+ # reduce 32 omitted
428
+
429
+ # reduce 33 omitted
430
+
431
+ module_eval(<<'.,.,', 'parser.y', 74)
432
+ def _reduce_34(val, _values, result)
433
+ result = Atoms::Literal.new(:value => val[0], :type => :string)
434
+ result
435
+ end
436
+ .,.,
437
+
438
+ module_eval(<<'.,.,', 'parser.y', 75)
439
+ def _reduce_35(val, _values, result)
440
+ result = Atoms::Literal.new(:value => val[0], :type => :float)
441
+ result
442
+ end
443
+ .,.,
444
+
445
+ module_eval(<<'.,.,', 'parser.y', 76)
446
+ def _reduce_36(val, _values, result)
447
+ result = Atoms::Literal.new(:value => val[0], :type => :int)
448
+ result
449
+ end
450
+ .,.,
451
+
452
+ module_eval(<<'.,.,', 'parser.y', 77)
453
+ def _reduce_37(val, _values, result)
454
+ result = Atoms::Literal.new(:value => val[0], :type => :datetime)
455
+ result
456
+ end
457
+ .,.,
458
+
459
+ module_eval(<<'.,.,', 'parser.y', 81)
460
+ def _reduce_38(val, _values, result)
461
+ result = Atoms::Column.new(:name => val[0])
462
+ result
463
+ end
464
+ .,.,
465
+
466
+ module_eval(<<'.,.,', 'parser.y', 82)
467
+ def _reduce_39(val, _values, result)
468
+ result = Atoms::Column.new(:name => val[0], :table=> val[2])
469
+ result
470
+ end
471
+ .,.,
472
+
473
+ module_eval(<<'.,.,', 'parser.y', 83)
474
+ def _reduce_40(val, _values, result)
475
+ result = Atoms::Column.new(:name => val[4], :table=> val[2], :space => val[0])
476
+ result
477
+ end
478
+ .,.,
479
+
480
+ def _reduce_none(val, _values, result)
481
+ val[0]
482
+ end
483
+
484
+ end # class Parser
485
+ end # module SQLSearch
@@ -0,0 +1,66 @@
1
+ class SQLSearch::Parser
2
+
3
+ option
4
+ ignorecase
5
+
6
+ macro
7
+ BLANK [\ \t]+
8
+ STRING [^']+
9
+ APPROXNUM {INTNUM}\.{INTNUM}
10
+ INTNUM \d+
11
+ COMPARISON (<>|=|[<][=]|[<]|[>][=]|[>])
12
+
13
+ NAME [A-z_]([A-z0-9_]*)
14
+
15
+ IS is
16
+ NOT not
17
+ NULLX null
18
+ IN in
19
+ OR or
20
+ AND and
21
+ BETWEEN between
22
+
23
+ YEARS \d+
24
+ MONTHS \d{2}
25
+ DAYS \d{2}
26
+ HOURS \d{2}
27
+ MINUTES \d{2}
28
+ SECONDS \d{2}
29
+ UTC_OFFSET ([+-]{HOURS}:{MINUTES}|Z)
30
+ TIME {YEARS}-{MONTHS}-{DAYS}T{HOURS}:{MINUTES}:{SECONDS}{UTC_OFFSET}
31
+
32
+ rule
33
+ {BLANK}
34
+ {APPROXNUM} { [:APPROXNUM, text.to_f] }
35
+ {INTNUM} { [:INTNUM, text.to_i] }
36
+ '{TIME}' { [:TIME, DateTime.iso8601(text[1...-1])] }
37
+ '{STRING}' { [:STRING, text[1...-1]] }
38
+ IS { [:IS, text] }
39
+ NOT { [:NOT, text] }
40
+ NULL { [:NULL, text.upcase] }
41
+ IN { [:IN, text] }
42
+ OR { [:OR, text] }
43
+ AND { [:AND, text] }
44
+ BETWEEN { [:BETWEEN, text] }
45
+ LIKE { [:LIKE, text] }
46
+ {COMPARISON} { [:COMPARISON, text] }
47
+ {NAME} { [:NAME, text] }
48
+ \( { [:LPAREN, text] }
49
+ \) { [:RPAREN, text] }
50
+ \. { [:DOT, text] }
51
+ \, { [:COMMA, text] }
52
+ \+ { [:ADD, text] }
53
+ \- { [:SUBTRACT, text] }
54
+ \/ { [:DIVIDE, text] }
55
+ \* { [:MULTIPLY, text] }
56
+ inner
57
+
58
+ def tokenize(code)
59
+ scan_setup(code)
60
+ tokens = []
61
+ while token = next_token
62
+ tokens << token
63
+ end
64
+ tokens
65
+ end
66
+ end
@@ -0,0 +1,148 @@
1
+ #--
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by rex 1.0.5
4
+ # from lexical definition file "lib/sql_search/parser.rex".
5
+ #++
6
+
7
+ require 'racc/parser'
8
+ class SQLSearch::Parser < Racc::Parser
9
+ require 'strscan'
10
+
11
+ class ScanError < StandardError ; end
12
+
13
+ attr_reader :lineno
14
+ attr_reader :filename
15
+ attr_accessor :state
16
+
17
+ def scan_setup(str)
18
+ @ss = StringScanner.new(str)
19
+ @lineno = 1
20
+ @state = nil
21
+ end
22
+
23
+ def action
24
+ yield
25
+ end
26
+
27
+ def scan_str(str)
28
+ scan_setup(str)
29
+ do_parse
30
+ end
31
+ alias :scan :scan_str
32
+
33
+ def load_file( filename )
34
+ @filename = filename
35
+ open(filename, "r") do |f|
36
+ scan_setup(f.read)
37
+ end
38
+ end
39
+
40
+ def scan_file( filename )
41
+ load_file(filename)
42
+ do_parse
43
+ end
44
+
45
+
46
+ def next_token
47
+ return if @ss.eos?
48
+
49
+ # skips empty actions
50
+ until token = _next_token or @ss.eos?; end
51
+ token
52
+ end
53
+
54
+ def _next_token
55
+ text = @ss.peek(1)
56
+ @lineno += 1 if text == "\n"
57
+ token = case @state
58
+ when nil
59
+ case
60
+ when (text = @ss.scan(/[ \t]+/i))
61
+ ;
62
+
63
+ when (text = @ss.scan(/\d+\.\d+/i))
64
+ action { [:APPROXNUM, text.to_f] }
65
+
66
+ when (text = @ss.scan(/\d+/i))
67
+ action { [:INTNUM, text.to_i] }
68
+
69
+ when (text = @ss.scan(/'\d+-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}([+-]\d{2}:\d{2}|Z)'/i))
70
+ action { [:TIME, DateTime.iso8601(text[1...-1])] }
71
+
72
+ when (text = @ss.scan(/'[^']+'/i))
73
+ action { [:STRING, text[1...-1]] }
74
+
75
+ when (text = @ss.scan(/IS/i))
76
+ action { [:IS, text] }
77
+
78
+ when (text = @ss.scan(/NOT/i))
79
+ action { [:NOT, text] }
80
+
81
+ when (text = @ss.scan(/NULL/i))
82
+ action { [:NULL, text.upcase] }
83
+
84
+ when (text = @ss.scan(/IN/i))
85
+ action { [:IN, text] }
86
+
87
+ when (text = @ss.scan(/OR/i))
88
+ action { [:OR, text] }
89
+
90
+ when (text = @ss.scan(/AND/i))
91
+ action { [:AND, text] }
92
+
93
+ when (text = @ss.scan(/BETWEEN/i))
94
+ action { [:BETWEEN, text] }
95
+
96
+ when (text = @ss.scan(/LIKE/i))
97
+ action { [:LIKE, text] }
98
+
99
+ when (text = @ss.scan(/(<>|=|[<][=]|[<]|[>][=]|[>])/i))
100
+ action { [:COMPARISON, text] }
101
+
102
+ when (text = @ss.scan(/[A-z_]([A-z0-9_]*)/i))
103
+ action { [:NAME, text] }
104
+
105
+ when (text = @ss.scan(/\(/i))
106
+ action { [:LPAREN, text] }
107
+
108
+ when (text = @ss.scan(/\)/i))
109
+ action { [:RPAREN, text] }
110
+
111
+ when (text = @ss.scan(/\./i))
112
+ action { [:DOT, text] }
113
+
114
+ when (text = @ss.scan(/\,/i))
115
+ action { [:COMMA, text] }
116
+
117
+ when (text = @ss.scan(/\+/i))
118
+ action { [:ADD, text] }
119
+
120
+ when (text = @ss.scan(/\-/i))
121
+ action { [:SUBTRACT, text] }
122
+
123
+ when (text = @ss.scan(/\//i))
124
+ action { [:DIVIDE, text] }
125
+
126
+ when (text = @ss.scan(/\*/i))
127
+ action { [:MULTIPLY, text] }
128
+
129
+ else
130
+ text = @ss.string[@ss.pos .. -1]
131
+ raise ScanError, "can not match: '" + text + "'"
132
+ end # if
133
+
134
+ else
135
+ raise ScanError, "undefined state: '" + state.to_s + "'"
136
+ end # case state
137
+ token
138
+ end # def _next_token
139
+
140
+ def tokenize(code)
141
+ scan_setup(code)
142
+ tokens = []
143
+ while token = next_token
144
+ tokens << token
145
+ end
146
+ tokens
147
+ end
148
+ end # class
@@ -0,0 +1,97 @@
1
+ class SQLSearch::Parser
2
+
3
+ rule
4
+ /* search conditions */
5
+
6
+ search_condition:
7
+ search_condition OR search_condition { result = Conditions::Or.new(:left => val[0], :right => val[2]) }
8
+ |search_condition AND search_condition { result = Conditions::And.new(:left => val[0], :right => val[2]) }
9
+ |NOT search_condition { result = Conditions::Not.new(:value => val[1]) }
10
+ |LPAREN search_condition RPAREN
11
+ |predicate
12
+ ;
13
+
14
+ predicate:
15
+ comparison_predicate
16
+ |between_predicate
17
+ |like_predicate
18
+ |test_for_null
19
+ |in_predicate
20
+ ;
21
+
22
+ comparison_predicate:
23
+ scalar_exp COMPARISON scalar_exp { result = Comparison.new(:left => val[0], :right => val[2], :operator => val[1].to_sym) }
24
+ ;
25
+
26
+ between_predicate:
27
+ scalar_exp NOT BETWEEN scalar_exp AND scalar_exp
28
+ |scalar_exp BETWEEN scalar_exp AND scalar_exp
29
+ ;
30
+
31
+ like_predicate:
32
+ scalar_exp NOT LIKE atom opt_escape { result = Conditions::Not.new(:value => Comparison.new(:left => val[0], :right => val[3], :operator => :LIKE)) }
33
+ |scalar_exp LIKE atom opt_escape { result = Comparison.new(:left => val[0], :right => val[2], :operator => :LIKE) }
34
+ ;
35
+
36
+ opt_escape:
37
+ /* empty */
38
+ |ESCAPE atom
39
+ ;
40
+
41
+ test_for_null:
42
+ column_ref IS NOT NULL { result = Comparison.new(:left => val[0], :right => val[3], :operator => :'<>') }
43
+ |column_ref IS NULL { result = Comparison.new(:left => val[0], :right => val[2], :operator => :'=') }
44
+ ;
45
+
46
+ in_predicate:
47
+ scalar_exp NOT IN LPAREN atom_commalist RPAREN { result = Conditions::Not.new(:value => In.new(:left => val[0], :right => Atoms::InValues.new(:values => val[4]))) }
48
+ |scalar_exp IN LPAREN atom_commalist RPAREN { result = In.new(:left => val[0], :right => Atoms::InValues.new(:values => val[3])) }
49
+ ;
50
+
51
+ atom_commalist:
52
+ atom { result = [val[0]] }
53
+ |atom_commalist COMMA atom { result = val[0].concat([val[2]]) }
54
+ ;
55
+
56
+ /* scalar expressions */
57
+
58
+ scalar_exp:
59
+ scalar_exp ADD scalar_exp { result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'+')}
60
+ |scalar_exp SUBTRACT scalar_exp { result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'-')}
61
+ |scalar_exp MULTIPLY scalar_exp { result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'*')}
62
+ |scalar_exp DIVIDE scalar_exp { result = Atoms::Scalar.new(:left => val[0], :right => val[2], :operation => :'/')}
63
+ |ADD scalar_exp { result = Atoms::UnaryScalar.new(:value => val[1], :operation => :'+')}
64
+ |SUBTRACT scalar_exp { result = Atoms::UnaryScalar.new(:value => val[1], :operation => :'-')}
65
+ |atom
66
+ |column_ref
67
+ |LPAREN scalar_exp RPAREN
68
+ ;
69
+
70
+ atom:
71
+ literal
72
+ ;
73
+
74
+ literal:
75
+ STRING { result = Atoms::Literal.new(:value => val[0], :type => :string) }
76
+ |APPROXNUM { result = Atoms::Literal.new(:value => val[0], :type => :float) }
77
+ |INTNUM { result = Atoms::Literal.new(:value => val[0], :type => :int) }
78
+ |TIME { result = Atoms::Literal.new(:value => val[0], :type => :datetime) }
79
+ ;
80
+
81
+ column_ref:
82
+ NAME { result = Atoms::Column.new(:name => val[0]) }
83
+ |NAME DOT NAME { result = Atoms::Column.new(:name => val[0], :table=> val[2]) }
84
+ |NAME DOT NAME DOT NAME { result = Atoms::Column.new(:name => val[4], :table=> val[2], :space => val[0]) }
85
+ ;
86
+
87
+ end
88
+
89
+ ---- header
90
+ require 'date'
91
+ require_relative 'parser.rex.rb'
92
+
93
+ ---- inner
94
+ def parse(input)
95
+ scan_str(input)
96
+ end
97
+
@@ -0,0 +1,3 @@
1
+ module SQLSearch
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,126 @@
1
+ module SQLSearch
2
+ module Conditions
3
+ class And
4
+ attr_reader :left, :right
5
+ def initialize options
6
+ @left = options[:left]; @right = options[:right]
7
+ end
8
+
9
+ def to_s
10
+ "(#{left}) AND (#{right})"
11
+ end
12
+ end
13
+
14
+ class Or
15
+ attr_reader :left, :right
16
+ def initialize options
17
+ @left = options[:left]; @right = options[:right]
18
+ end
19
+
20
+ def to_s
21
+ "(#{left}) OR (#{right})"
22
+ end
23
+ end
24
+
25
+ class Not
26
+ attr_reader :value
27
+ def initialize options
28
+ @value = options[:value]
29
+ end
30
+
31
+ def to_s
32
+ "NOT(#{value})"
33
+ end
34
+ end
35
+ end
36
+
37
+ class Comparison
38
+ attr_reader :left, :right, :operator
39
+
40
+ def initialize options
41
+ @left = options[:left]
42
+ @right = options[:right]
43
+ @operator = options[:operator]
44
+ end
45
+
46
+ def to_s
47
+ "#{left} #{operator} #{right}"
48
+ end
49
+ end
50
+
51
+ class In < Comparison
52
+ def initialize options
53
+ super options
54
+ @operator = :IN
55
+ end
56
+ end
57
+
58
+ module Atoms
59
+ class InValues
60
+ attr_reader :values
61
+ def initialize options
62
+ @values = options[:values]
63
+ end
64
+
65
+ def to_s
66
+ "(#{values.join(', ')})"
67
+ end
68
+ end
69
+
70
+ class Scalar
71
+ attr_reader :left, :right, :operation
72
+ def initialize options
73
+ @left = options[:left]
74
+ @right = options[:right]
75
+ @operation = options[:operation]
76
+ end
77
+
78
+ def to_s
79
+ "#{left} #{operation} #{right}"
80
+ end
81
+ end
82
+
83
+ class UnaryScalar < Scalar
84
+ attr_reader :value, :operation
85
+ def initialize options
86
+ @value = options[:value]
87
+ @operation = options[:operation]
88
+ end
89
+
90
+ def to_s
91
+ "#{operation}#{value}"
92
+ end
93
+ end
94
+
95
+ class Literal
96
+ attr_reader :value, :type
97
+ def initialize options
98
+ @value = options[:value]
99
+ @type = options[:type]
100
+ end
101
+
102
+ def to_s
103
+ case type
104
+ when :string then "'#{value}'"
105
+ else "#{value}"
106
+ end
107
+ end
108
+ end
109
+
110
+ class Column
111
+ attr_reader :name, :table, :space
112
+
113
+ def initialize options
114
+ @name = options[:name]
115
+ @table = options[:table]
116
+ @space = options[:space]
117
+ end
118
+
119
+ def to_s
120
+ [space,table,name].compact.map { |a| "`#{a}`" }.join('.')
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ require 'sql_search/parser.racc.rb'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sql_search_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Antoine Niek
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rexical
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: racc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Simple SQL search conditions parser (where clause)
70
+ email: antoineniek@gmail.com
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - LICENSE
76
+ - README.md
77
+ - Rakefile
78
+ - lib/sql_search_parser.rb
79
+ - lib/sql_search/parser.rex.rb
80
+ - lib/sql_search/parser.y
81
+ - lib/sql_search/parser.rex
82
+ - lib/sql_search/version.rb
83
+ - lib/sql_search/parser.racc.rb
84
+ homepage: https://github.com/zapo/sql_search_parser
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.0.14
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Simple SQL search conditions parser (where clause)
108
+ test_files: []