sparkql 1.2.2 → 1.2.7
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.
- checksums.yaml +5 -13
- data/CHANGELOG.md +21 -0
- data/GRAMMAR.md +5 -4
- data/Gemfile +1 -2
- data/VERSION +1 -1
- data/lib/sparkql/function_resolver.rb +768 -676
- data/lib/sparkql/parser.rb +198 -178
- data/lib/sparkql/parser.y +4 -2
- data/lib/sparkql/parser_compatibility.rb +36 -17
- data/lib/sparkql/parser_tools.rb +67 -23
- data/sparkql.gemspec +19 -17
- data/test/unit/function_resolver_test.rb +455 -191
- data/test/unit/parser_compatability_test.rb +15 -0
- data/test/unit/parser_test.rb +148 -13
- metadata +34 -35
- data/.ruby-version +0 -1
|
@@ -565,4 +565,19 @@ class ParserCompatabilityTest < Test::Unit::TestCase
|
|
|
565
565
|
assert parser.send(:check_type!, expression, :datetime)
|
|
566
566
|
assert_equal '3', parser.escape_value(expression)
|
|
567
567
|
end
|
|
568
|
+
|
|
569
|
+
test "function with field and arithmetic" do
|
|
570
|
+
filter = "year(CloseDate) add 1 Eq 2017"
|
|
571
|
+
parser = Parser.new
|
|
572
|
+
expression = parser.tokenize(filter).first
|
|
573
|
+
assert parser.send(:check_type!, expression, :datetime)
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
test "Cannot perform arithmetic on a String field" do
|
|
577
|
+
filter = "City Add 3.0 Eq 'Fargo'"
|
|
578
|
+
parser = Parser.new
|
|
579
|
+
expression = parser.tokenize(filter).first
|
|
580
|
+
# Type mismatch
|
|
581
|
+
assert !parser.send(:check_type!, expression, :datetime)
|
|
582
|
+
end
|
|
568
583
|
end
|
data/test/unit/parser_test.rb
CHANGED
|
@@ -125,19 +125,23 @@ class ParserTest < Test::Unit::TestCase
|
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
def test_function_days
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
filter = "OriginalEntryTimestamp Ge days(-7)"
|
|
128
|
+
dt = DateTime.new(2021, 2, 22, 0, 0, 0, 0)
|
|
129
|
+
DateTime.expects(:now).returns(dt)
|
|
131
130
|
@parser = Parser.new
|
|
132
|
-
expressions = @parser.parse(
|
|
133
|
-
assert !@parser.errors
|
|
134
|
-
assert_equal
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
expressions = @parser.parse "ExpirationDate Gt days(10)"
|
|
132
|
+
assert !@parser.errors?
|
|
133
|
+
assert_equal "2021-03-04", expressions.first[:value]
|
|
134
|
+
assert_equal 'days(10)', expressions.first[:condition]
|
|
135
|
+
end
|
|
137
136
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
def test_function_weekdays
|
|
138
|
+
dt = DateTime.new(2021, 2, 22, 0, 0, 0, 0)
|
|
139
|
+
DateTime.expects(:now).returns(dt)
|
|
140
|
+
@parser = Parser.new
|
|
141
|
+
expressions = @parser.parse "ExpirationDate Gt weekdays(10)"
|
|
142
|
+
assert !@parser.errors?
|
|
143
|
+
assert_equal "2021-03-08", expressions.first[:value]
|
|
144
|
+
assert_equal 'weekdays(10)', expressions.first[:condition]
|
|
141
145
|
end
|
|
142
146
|
|
|
143
147
|
def test_function_now
|
|
@@ -232,6 +236,54 @@ class ParserTest < Test::Unit::TestCase
|
|
|
232
236
|
assert_equal 'Mod', field_manipulations[:op]
|
|
233
237
|
end
|
|
234
238
|
|
|
239
|
+
test 'Mod returns decimal precision' do
|
|
240
|
+
@parser = Parser.new
|
|
241
|
+
filter = "Baths Eq 32.7 Mod 20.7"
|
|
242
|
+
expressions = @parser.parse(filter)
|
|
243
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
244
|
+
assert_equal '12.0', expressions.first[:value]
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
test 'Adding returns decimal precision' do
|
|
248
|
+
@parser = Parser.new
|
|
249
|
+
filter = "Baths Eq 0.1 Add 0.2"
|
|
250
|
+
expressions = @parser.parse(filter)
|
|
251
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
252
|
+
assert_equal '0.3', expressions.first[:value]
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
test 'Subtracting returns decimal precision' do
|
|
256
|
+
@parser = Parser.new
|
|
257
|
+
filter = "Baths Eq 0.3 Sub 0.1"
|
|
258
|
+
expressions = @parser.parse(filter)
|
|
259
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
260
|
+
assert_equal '0.2', expressions.first[:value]
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
test 'Division returns decimal precision' do
|
|
264
|
+
@parser = Parser.new
|
|
265
|
+
filter = "Baths Eq 0.6 Div 0.2"
|
|
266
|
+
expressions = @parser.parse(filter)
|
|
267
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
268
|
+
assert_equal '3.0', expressions.first[:value]
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
test 'Arithmetic rounds to 20 decimal places' do
|
|
272
|
+
@parser = Parser.new
|
|
273
|
+
filter = "Baths Eq 7 Div 10.1"
|
|
274
|
+
expressions = @parser.parse(filter)
|
|
275
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
276
|
+
assert_equal '0.69306930693069306931', expressions.first[:value]
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
test 'Multiplication returns decimal precision' do
|
|
280
|
+
@parser = Parser.new
|
|
281
|
+
filter = "Baths Eq 7 Mul 0.1"
|
|
282
|
+
expressions = @parser.parse(filter)
|
|
283
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
284
|
+
assert_equal '0.7', expressions.first[:value]
|
|
285
|
+
end
|
|
286
|
+
|
|
235
287
|
test 'arithmetic with field function' do
|
|
236
288
|
@parser = Parser.new
|
|
237
289
|
filter = "floor(Baths) Add 2 Eq 1"
|
|
@@ -340,10 +392,40 @@ class ParserTest < Test::Unit::TestCase
|
|
|
340
392
|
test "invalid regex" do
|
|
341
393
|
filter = "ParcelNumber Eq regex('[1234', '')"
|
|
342
394
|
@parser = Parser.new
|
|
343
|
-
|
|
395
|
+
@parser.parse(filter)
|
|
344
396
|
assert @parser.errors?, "Parser error expected due to invalid regex"
|
|
345
397
|
end
|
|
346
398
|
|
|
399
|
+
test "dayofyear function parses" do
|
|
400
|
+
filter = "dayofyear(DatetimeField) Eq 2012"
|
|
401
|
+
@parser = Parser.new
|
|
402
|
+
expressions = @parser.parse(filter)
|
|
403
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
404
|
+
function = expressions.first[:field_manipulations]
|
|
405
|
+
assert_equal 'dayofyear', function[:function_name]
|
|
406
|
+
assert_equal 'DatetimeField', function[:function_parameters].first
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
test "dayofweek function parses" do
|
|
410
|
+
filter = "dayofweek(DatetimeField) Eq 7"
|
|
411
|
+
@parser = Parser.new
|
|
412
|
+
expressions = @parser.parse(filter)
|
|
413
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
414
|
+
function = expressions.first[:field_manipulations]
|
|
415
|
+
assert_equal 'dayofweek', function[:function_name]
|
|
416
|
+
assert_equal 'DatetimeField', function[:function_parameters].first
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
test "weekdays function resolves" do
|
|
420
|
+
filter = "DatetimeField Eq weekdays(10)"
|
|
421
|
+
@parser = Parser.new
|
|
422
|
+
expressions = @parser.parse(filter)
|
|
423
|
+
assert !@parser.errors?, @parser.errors.inspect
|
|
424
|
+
function = expressions.first
|
|
425
|
+
assert_equal 'weekdays', function[:function_name]
|
|
426
|
+
assert_equal 10, function[:function_parameters].first
|
|
427
|
+
end
|
|
428
|
+
|
|
347
429
|
test "allow timezone offsets" do
|
|
348
430
|
values = [
|
|
349
431
|
"2013-07-26",
|
|
@@ -370,7 +452,7 @@ class ParserTest < Test::Unit::TestCase
|
|
|
370
452
|
assert_equal expressions.first[:value], value, "#{value} failed"
|
|
371
453
|
end
|
|
372
454
|
end
|
|
373
|
-
|
|
455
|
+
|
|
374
456
|
test "Location Eq polygon()" do
|
|
375
457
|
filter = "Location Eq polygon('35.12 -68.33, 35.13 -68.33, 35.13 -68.32, 35.12 -68.32')"
|
|
376
458
|
@parser = Parser.new
|
|
@@ -732,6 +814,16 @@ class ParserTest < Test::Unit::TestCase
|
|
|
732
814
|
parser_errors("Field Eq -'Stringval'")
|
|
733
815
|
end
|
|
734
816
|
|
|
817
|
+
|
|
818
|
+
test "field negation" do
|
|
819
|
+
@parser = Parser.new
|
|
820
|
+
expressions = @parser.parse('-Test Eq 10')
|
|
821
|
+
assert !@parser.errors?
|
|
822
|
+
|
|
823
|
+
assert_equal 'Negation', expressions.first[:field_manipulations][:op]
|
|
824
|
+
assert_equal 'Test', expressions.first[:field]
|
|
825
|
+
end
|
|
826
|
+
|
|
735
827
|
def test_substring
|
|
736
828
|
filter = "Name Eq substring('Andy', 1)"
|
|
737
829
|
@parser = Parser.new
|
|
@@ -1097,6 +1189,49 @@ class ParserTest < Test::Unit::TestCase
|
|
|
1097
1189
|
parser_errors("1 Add 1 Eq 2")
|
|
1098
1190
|
end
|
|
1099
1191
|
|
|
1192
|
+
test "field grouping" do
|
|
1193
|
+
@parser = Parser.new
|
|
1194
|
+
expressions = @parser.parse('(Test) Eq 10')
|
|
1195
|
+
assert !@parser.errors?
|
|
1196
|
+
|
|
1197
|
+
assert_equal 'Group', expressions.first[:field_manipulations][:op]
|
|
1198
|
+
end
|
|
1199
|
+
|
|
1200
|
+
test "grouping arithmetic" do
|
|
1201
|
+
@parser = Parser.new
|
|
1202
|
+
expressions = @parser.parse('(Test mul 10) sub 2 Eq 10')
|
|
1203
|
+
assert !@parser.errors?
|
|
1204
|
+
|
|
1205
|
+
assert_equal 'Sub', expressions.first[:field_manipulations][:op]
|
|
1206
|
+
assert_equal 'Group', expressions.first[:field_manipulations][:lhs][:op]
|
|
1207
|
+
end
|
|
1208
|
+
|
|
1209
|
+
test "grouping literal" do
|
|
1210
|
+
@parser = Parser.new
|
|
1211
|
+
expressions = @parser.parse('Test Eq (5 sub 5) mul 5 ')
|
|
1212
|
+
assert !@parser.errors?
|
|
1213
|
+
|
|
1214
|
+
assert_equal '0', expressions.first[:value]
|
|
1215
|
+
end
|
|
1216
|
+
|
|
1217
|
+
test 'Arithmetic grouping should not influence expression grouping' do
|
|
1218
|
+
filter = "(BathroomsTotalDecimal add (5 mul 5)) Eq ((3.4 add 2.6) mul (1 add 1))"
|
|
1219
|
+
@parser = Parser.new
|
|
1220
|
+
expressions = @parser.parse(filter)
|
|
1221
|
+
assert !@parser.errors?
|
|
1222
|
+
assert_equal 0, expressions.first[:level]
|
|
1223
|
+
assert_equal 0, expressions.first[:block_group]
|
|
1224
|
+
|
|
1225
|
+
filter = "((BathroomsTotalDecimal add (5 mul 5)) Eq ((3.4 add 2.6) mul (1 add 1))) And BathroomsTotalDecimal Eq 5"
|
|
1226
|
+
@parser = Parser.new
|
|
1227
|
+
expressions = @parser.parse(filter)
|
|
1228
|
+
assert !@parser.errors?
|
|
1229
|
+
assert_equal 1, expressions.first[:level]
|
|
1230
|
+
assert_equal 1, expressions.first[:block_group]
|
|
1231
|
+
assert_equal 0, expressions.last[:level]
|
|
1232
|
+
assert_equal 0, expressions.last[:block_group]
|
|
1233
|
+
end
|
|
1234
|
+
|
|
1100
1235
|
private
|
|
1101
1236
|
|
|
1102
1237
|
def parser_errors(filter)
|
metadata
CHANGED
|
@@ -1,99 +1,99 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sparkql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Wade McEwen
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-05-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: georuby
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - ~>
|
|
17
|
+
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '2.0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - ~>
|
|
24
|
+
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '2.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: ci_reporter
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - ~>
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 1.
|
|
33
|
+
version: '1.6'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - ~>
|
|
38
|
+
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 1.
|
|
40
|
+
version: '1.6'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: mocha
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- - ~>
|
|
45
|
+
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
47
|
+
version: 0.12.0
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- - ~>
|
|
52
|
+
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
54
|
+
version: 0.12.0
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
56
|
+
name: racc
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- - ~>
|
|
59
|
+
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version:
|
|
61
|
+
version: 1.4.8
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- - ~>
|
|
66
|
+
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version:
|
|
68
|
+
version: 1.4.8
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
70
|
+
name: rake
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- - ~>
|
|
73
|
+
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
75
|
+
version: 0.9.2
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- - ~>
|
|
80
|
+
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
82
|
+
version: 0.9.2
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name:
|
|
84
|
+
name: test-unit
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- - ~>
|
|
87
|
+
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version:
|
|
89
|
+
version: 2.1.0
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
|
-
- - ~>
|
|
94
|
+
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version:
|
|
96
|
+
version: 2.1.0
|
|
97
97
|
description: Specification and base implementation of the Spark API parsing system.
|
|
98
98
|
email:
|
|
99
99
|
- wade@fbsdata.com
|
|
@@ -101,8 +101,7 @@ executables: []
|
|
|
101
101
|
extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
|
103
103
|
files:
|
|
104
|
-
- .gitignore
|
|
105
|
-
- .ruby-version
|
|
104
|
+
- ".gitignore"
|
|
106
105
|
- CHANGELOG.md
|
|
107
106
|
- GRAMMAR.md
|
|
108
107
|
- Gemfile
|
|
@@ -149,17 +148,17 @@ require_paths:
|
|
|
149
148
|
- lib
|
|
150
149
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
151
150
|
requirements:
|
|
152
|
-
- -
|
|
151
|
+
- - ">="
|
|
153
152
|
- !ruby/object:Gem::Version
|
|
154
|
-
version: '
|
|
153
|
+
version: '2.3'
|
|
155
154
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
155
|
requirements:
|
|
157
|
-
- -
|
|
156
|
+
- - ">="
|
|
158
157
|
- !ruby/object:Gem::Version
|
|
159
158
|
version: '0'
|
|
160
159
|
requirements: []
|
|
161
160
|
rubyforge_project: sparkql
|
|
162
|
-
rubygems_version: 2.
|
|
161
|
+
rubygems_version: 2.7.6
|
|
163
162
|
signing_key:
|
|
164
163
|
specification_version: 4
|
|
165
164
|
summary: API Parser engine for filter searching
|
data/.ruby-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.9.3
|