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 +7 -0
- data/LICENSE +21 -0
- data/README.md +50 -0
- data/Rakefile +26 -0
- data/lib/sql_search/parser.racc.rb +485 -0
- data/lib/sql_search/parser.rex +66 -0
- data/lib/sql_search/parser.rex.rb +148 -0
- data/lib/sql_search/parser.y +97 -0
- data/lib/sql_search/version.rb +3 -0
- data/lib/sql_search_parser.rb +126 -0
- metadata +108 -0
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,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: []
|