sparkql 1.2.4 → 1.2.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +16 -0
- data/Gemfile +1 -2
- data/VERSION +1 -1
- data/lib/sparkql/function_resolver.rb +772 -676
- data/lib/sparkql/parser.rb +1 -1
- data/lib/sparkql/parser_compatibility.rb +1 -1
- data/lib/sparkql/parser_tools.rb +4 -0
- data/sparkql.gemspec +19 -17
- data/test/unit/function_resolver_test.rb +469 -191
- data/test/unit/parser_test.rb +65 -13
- metadata +34 -35
- data/.ruby-version +0 -1
data/lib/sparkql/parser.rb
CHANGED
@@ -85,7 +85,7 @@ module Sparkql::ParserCompatibility
|
|
85
85
|
|
86
86
|
# Delegator for methods to process the error list.
|
87
87
|
def process_errors
|
88
|
-
Sparkql::ErrorsProcessor.new(
|
88
|
+
Sparkql::ErrorsProcessor.new(errors)
|
89
89
|
end
|
90
90
|
|
91
91
|
# delegate :errors?, :fatal_errors?, :dropped_errors?, :recovered_errors?, :to => :process_errors
|
data/lib/sparkql/parser_tools.rb
CHANGED
@@ -126,6 +126,8 @@ module Sparkql::ParserTools
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def tokenize_arithmetic_group(lhs)
|
129
|
+
@lexer.leveldown
|
130
|
+
@lexer.block_group_identifier -= 1
|
129
131
|
lhs = {type: :field, value: lhs} if lhs.is_a?(String)
|
130
132
|
{
|
131
133
|
type: :arithmetic,
|
@@ -260,6 +262,8 @@ module Sparkql::ParserTools
|
|
260
262
|
end
|
261
263
|
|
262
264
|
def group_fold(exp)
|
265
|
+
@lexer.leveldown
|
266
|
+
@lexer.block_group_identifier -= 1
|
263
267
|
exp
|
264
268
|
end
|
265
269
|
|
data/sparkql.gemspec
CHANGED
@@ -1,30 +1,32 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$LOAD_PATH.push File.expand_path('lib', __dir__)
|
4
|
+
require 'sparkql/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
7
|
+
s.name = 'sparkql'
|
7
8
|
s.version = Sparkql::VERSION
|
8
|
-
s.authors = [
|
9
|
-
s.email = [
|
10
|
-
s.homepage =
|
11
|
-
s.summary =
|
12
|
-
s.description =
|
9
|
+
s.authors = ['Wade McEwen']
|
10
|
+
s.email = ['wade@fbsdata.com']
|
11
|
+
s.homepage = ''
|
12
|
+
s.summary = 'API Parser engine for filter searching'
|
13
|
+
s.description = 'Specification and base implementation of the Spark API parsing system.'
|
14
|
+
|
15
|
+
s.rubyforge_project = 'sparkql'
|
13
16
|
|
14
|
-
s.rubyforge_project = "sparkql"
|
15
|
-
|
16
17
|
s.license = 'Apache 2.0'
|
17
|
-
|
18
|
+
|
18
19
|
s.files = `git ls-files`.split("\n")
|
19
20
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
-
s.require_paths = [
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
22
|
+
s.require_paths = ['lib']
|
23
|
+
|
24
|
+
s.required_ruby_version = '>= 2.3'
|
22
25
|
|
23
26
|
s.add_dependency 'georuby', '~> 2.0'
|
27
|
+
s.add_development_dependency 'ci_reporter', '~> 1.6'
|
28
|
+
s.add_development_dependency 'mocha', '~> 0.12.0'
|
24
29
|
s.add_development_dependency 'racc', '~> 1.4.8'
|
25
30
|
s.add_development_dependency 'rake', '~> 0.9.2'
|
26
31
|
s.add_development_dependency 'test-unit', '~> 2.1.0'
|
27
|
-
s.add_development_dependency 'ci_reporter', '~> 1.6'
|
28
|
-
s.add_development_dependency 'mocha', '~> 0.12.0'
|
29
|
-
|
30
32
|
end
|
@@ -1,21 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'test_helper'
|
2
4
|
require 'sparkql/geo'
|
3
5
|
|
4
6
|
class FunctionResolverTest < Test::Unit::TestCase
|
5
7
|
include Sparkql
|
6
|
-
|
7
|
-
EXAMPLE_DATE = DateTime.parse("2013-07-26T10:22:15.422804")
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
EXAMPLE_DATE = DateTime.parse('2013-07-26T10:22:15.422804')
|
10
|
+
|
11
|
+
test 'all with field' do
|
12
|
+
f = FunctionResolver.new('all', [
|
13
|
+
{ type: :field, value: 'Name' }
|
14
|
+
])
|
15
|
+
|
16
|
+
f.validate
|
17
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
18
|
+
value = f.call
|
19
|
+
|
20
|
+
assert_equal :function, value[:type]
|
21
|
+
assert_equal 'all', value[:value]
|
22
|
+
assert_equal 'Name', value[:args].first[:value]
|
23
|
+
end
|
24
|
+
|
25
|
+
test 'function parameters and name preserved' do
|
26
|
+
f = FunctionResolver.new('radius', [{ type: :character,
|
27
|
+
value: '35.12 -68.33' }, { type: :decimal, value: 1.0 }])
|
12
28
|
value = f.call
|
13
29
|
assert_equal 'radius', value[:function_name]
|
14
|
-
assert_equal([
|
30
|
+
assert_equal(['35.12 -68.33', 1.0], value[:function_parameters])
|
15
31
|
end
|
16
32
|
|
17
|
-
test
|
18
|
-
f = FunctionResolver.new('round', [{:
|
33
|
+
test 'round(float)' do
|
34
|
+
f = FunctionResolver.new('round', [{ type: :decimal, value: 0.5 }])
|
19
35
|
f.validate
|
20
36
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
21
37
|
value = f.call
|
@@ -23,22 +39,22 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
23
39
|
assert_equal '1', value[:value]
|
24
40
|
end
|
25
41
|
|
26
|
-
test
|
27
|
-
f = FunctionResolver.new('round', [{:
|
42
|
+
test 'round(Field)' do
|
43
|
+
f = FunctionResolver.new('round', [{ type: :field, value: 'ListPrice' }])
|
28
44
|
f.validate
|
29
45
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
30
46
|
value = f.call
|
31
47
|
|
32
48
|
assert_equal :function, value[:type]
|
33
49
|
assert_equal 'round', value[:value]
|
34
|
-
assert_equal
|
50
|
+
assert_equal 'ListPrice', value[:args].first[:value]
|
35
51
|
end
|
36
52
|
|
37
|
-
test
|
53
|
+
test 'substring character one index' do
|
38
54
|
f = FunctionResolver.new('substring', [
|
39
|
-
|
40
|
-
|
41
|
-
|
55
|
+
{ type: :character, value: 'ListPrice' },
|
56
|
+
{ type: :integer, value: 1 }
|
57
|
+
])
|
42
58
|
|
43
59
|
f.validate
|
44
60
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -48,26 +64,26 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
48
64
|
assert_equal 'istPrice', value[:value]
|
49
65
|
end
|
50
66
|
|
51
|
-
test
|
67
|
+
test 'substring character two indexes' do
|
52
68
|
f = FunctionResolver.new('substring', [
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
69
|
+
{ type: :character, value: 'alfb' },
|
70
|
+
{ type: :integer, value: 1 },
|
71
|
+
{ type: :integer, value: 2 }
|
72
|
+
])
|
57
73
|
|
58
74
|
f.validate
|
59
75
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
60
76
|
value = f.call
|
61
77
|
|
62
78
|
assert_equal :character, value[:type]
|
63
|
-
assert_equal
|
79
|
+
assert_equal 'lf', value[:value]
|
64
80
|
end
|
65
81
|
|
66
|
-
test
|
82
|
+
test 'substring character large first index' do
|
67
83
|
f = FunctionResolver.new('substring', [
|
68
|
-
|
69
|
-
|
70
|
-
|
84
|
+
{ type: :character, value: 'ListPrice' },
|
85
|
+
{ type: :integer, value: 10 }
|
86
|
+
])
|
71
87
|
|
72
88
|
f.validate
|
73
89
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -77,11 +93,11 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
77
93
|
assert_equal '', value[:value]
|
78
94
|
end
|
79
95
|
|
80
|
-
test
|
96
|
+
test 'substring field one index' do
|
81
97
|
f = FunctionResolver.new('substring', [
|
82
|
-
|
83
|
-
|
84
|
-
|
98
|
+
{ type: :field, value: 'ListPrice' },
|
99
|
+
{ type: :integer, value: 1 }
|
100
|
+
])
|
85
101
|
|
86
102
|
f.validate
|
87
103
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -89,16 +105,16 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
89
105
|
|
90
106
|
assert_equal :function, value[:type]
|
91
107
|
assert_equal 'substring', value[:value]
|
92
|
-
assert_equal
|
108
|
+
assert_equal 'ListPrice', value[:args].first[:value]
|
93
109
|
assert_equal 2, value[:args].size
|
94
110
|
end
|
95
111
|
|
96
|
-
test
|
112
|
+
test 'substring field two indexes' do
|
97
113
|
f = FunctionResolver.new('substring', [
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
114
|
+
{ type: :field, value: 'ListPrice' },
|
115
|
+
{ type: :integer, value: 1 },
|
116
|
+
{ type: :integer, value: 2 }
|
117
|
+
])
|
102
118
|
|
103
119
|
f.validate
|
104
120
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -106,28 +122,28 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
106
122
|
|
107
123
|
assert_equal :function, value[:type]
|
108
124
|
assert_equal 'substring', value[:value]
|
109
|
-
assert_equal
|
125
|
+
assert_equal 'ListPrice', value[:args].first[:value]
|
110
126
|
assert_equal 2, value[:args].last[:value]
|
111
127
|
end
|
112
128
|
|
113
|
-
test
|
129
|
+
test 'substring with negative M is a parse error' do
|
114
130
|
f = FunctionResolver.new('substring', [
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
131
|
+
{ type: :field, value: 'ListPrice' },
|
132
|
+
{ type: :integer, value: 1 },
|
133
|
+
{ type: :integer, value: -5 }
|
134
|
+
])
|
119
135
|
|
120
136
|
f.validate
|
121
137
|
f.call
|
122
138
|
assert f.errors?
|
123
139
|
end
|
124
140
|
|
125
|
-
test
|
141
|
+
test 'character substring with negative M is a parse error' do
|
126
142
|
f = FunctionResolver.new('substring', [
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
143
|
+
{ type: :character, value: 'ListPrice' },
|
144
|
+
{ type: :integer, value: 1 },
|
145
|
+
{ type: :integer, value: -5 }
|
146
|
+
])
|
131
147
|
|
132
148
|
f.validate
|
133
149
|
f.call
|
@@ -136,8 +152,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
136
152
|
|
137
153
|
test 'trim with field' do
|
138
154
|
f = FunctionResolver.new('trim', [
|
139
|
-
|
140
|
-
|
155
|
+
{ type: :field, value: 'Name' }
|
156
|
+
])
|
141
157
|
|
142
158
|
f.validate
|
143
159
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -145,13 +161,13 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
145
161
|
|
146
162
|
assert_equal :function, value[:type]
|
147
163
|
assert_equal 'trim', value[:value]
|
148
|
-
assert_equal
|
164
|
+
assert_equal 'Name', value[:args].first[:value]
|
149
165
|
end
|
150
166
|
|
151
167
|
test 'trim with character' do
|
152
168
|
f = FunctionResolver.new('trim', [
|
153
|
-
|
154
|
-
|
169
|
+
{ type: :character, value: ' val ' }
|
170
|
+
])
|
155
171
|
|
156
172
|
f.validate
|
157
173
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -162,7 +178,7 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
162
178
|
end
|
163
179
|
|
164
180
|
test "tolower('string')" do
|
165
|
-
f = FunctionResolver.new('tolower', [{:
|
181
|
+
f = FunctionResolver.new('tolower', [{ type: :character, value: 'STRING' }])
|
166
182
|
f.validate
|
167
183
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
168
184
|
value = f.call
|
@@ -170,18 +186,18 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
170
186
|
assert_equal "'string'", value[:value]
|
171
187
|
end
|
172
188
|
|
173
|
-
test
|
174
|
-
f = FunctionResolver.new('toupper', [{:
|
189
|
+
test 'toupper(SomeField)' do
|
190
|
+
f = FunctionResolver.new('toupper', [{ type: :field, value: 'City' }])
|
175
191
|
f.validate
|
176
192
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
177
193
|
value = f.call
|
178
194
|
assert_equal :function, value[:type]
|
179
195
|
assert_equal 'toupper', value[:value]
|
180
|
-
assert_equal
|
196
|
+
assert_equal 'City', value[:args].first[:value]
|
181
197
|
end
|
182
198
|
|
183
199
|
test "toupper('string')" do
|
184
|
-
f = FunctionResolver.new('toupper', [{:
|
200
|
+
f = FunctionResolver.new('toupper', [{ type: :character, value: 'string' }])
|
185
201
|
f.validate
|
186
202
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
187
203
|
value = f.call
|
@@ -189,18 +205,18 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
189
205
|
assert_equal "'STRING'", value[:value]
|
190
206
|
end
|
191
207
|
|
192
|
-
test
|
193
|
-
f = FunctionResolver.new('length', [{:
|
208
|
+
test 'length(SomeField)' do
|
209
|
+
f = FunctionResolver.new('length', [{ type: :field, value: 'City' }])
|
194
210
|
f.validate
|
195
211
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
196
212
|
value = f.call
|
197
213
|
assert_equal :function, value[:type]
|
198
214
|
assert_equal 'length', value[:value]
|
199
|
-
assert_equal
|
215
|
+
assert_equal 'City', value[:args].first[:value]
|
200
216
|
end
|
201
217
|
|
202
218
|
test "length('string')" do
|
203
|
-
f = FunctionResolver.new('length', [{:
|
219
|
+
f = FunctionResolver.new('length', [{ type: :character, value: 'string' }])
|
204
220
|
f.validate
|
205
221
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
206
222
|
value = f.call
|
@@ -208,7 +224,7 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
208
224
|
assert_equal '6', value[:value]
|
209
225
|
end
|
210
226
|
|
211
|
-
test
|
227
|
+
test 'now()' do
|
212
228
|
start = Time.now
|
213
229
|
f = FunctionResolver.new('now', [])
|
214
230
|
f.validate
|
@@ -216,10 +232,11 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
216
232
|
value = f.call
|
217
233
|
assert_equal :datetime, value[:type]
|
218
234
|
test_time = Time.parse(value[:value])
|
219
|
-
assert (
|
235
|
+
assert (test_time - start > -5 && test_time - start < 5),
|
236
|
+
"Time range off by more than five seconds #{test_time - start} '#{test_time} - #{start}'"
|
220
237
|
end
|
221
238
|
|
222
|
-
test
|
239
|
+
test 'mindatetime()' do
|
223
240
|
f = FunctionResolver.new('mindatetime', [])
|
224
241
|
f.validate
|
225
242
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -229,7 +246,7 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
229
246
|
assert_equal '1970-01-01T00:00:00+00:00', value[:value]
|
230
247
|
end
|
231
248
|
|
232
|
-
test
|
249
|
+
test 'maxdatetime()' do
|
233
250
|
f = FunctionResolver.new('maxdatetime', [])
|
234
251
|
f.validate
|
235
252
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
@@ -239,8 +256,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
239
256
|
assert_equal '9999-12-31T23:59:59+00:00', value[:value]
|
240
257
|
end
|
241
258
|
|
242
|
-
test
|
243
|
-
f = FunctionResolver.new('floor', [{:
|
259
|
+
test 'floor(float)' do
|
260
|
+
f = FunctionResolver.new('floor', [{ type: :decimal, value: 0.5 }])
|
244
261
|
f.validate
|
245
262
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
246
263
|
value = f.call
|
@@ -248,19 +265,19 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
248
265
|
assert_equal '0', value[:value]
|
249
266
|
end
|
250
267
|
|
251
|
-
test
|
252
|
-
f = FunctionResolver.new('floor', [{:
|
268
|
+
test 'floor(Field)' do
|
269
|
+
f = FunctionResolver.new('floor', [{ type: :field, value: 'ListPrice' }])
|
253
270
|
f.validate
|
254
271
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
255
272
|
value = f.call
|
256
273
|
|
257
274
|
assert_equal :function, value[:type]
|
258
275
|
assert_equal 'floor', value[:value]
|
259
|
-
assert_equal
|
276
|
+
assert_equal 'ListPrice', value[:args].first[:value]
|
260
277
|
end
|
261
278
|
|
262
|
-
test
|
263
|
-
f = FunctionResolver.new('ceiling', [{:
|
279
|
+
test 'ceiling(float)' do
|
280
|
+
f = FunctionResolver.new('ceiling', [{ type: :decimal, value: 0.5 }])
|
264
281
|
f.validate
|
265
282
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
266
283
|
value = f.call
|
@@ -268,93 +285,344 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
268
285
|
assert_equal '1', value[:value]
|
269
286
|
end
|
270
287
|
|
271
|
-
test
|
272
|
-
f = FunctionResolver.new('ceiling', [{:
|
288
|
+
test 'ceiling(Field)' do
|
289
|
+
f = FunctionResolver.new('ceiling', [{ type: :field, value: 'ListPrice' }])
|
273
290
|
f.validate
|
274
291
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
275
292
|
value = f.call
|
276
293
|
|
277
294
|
assert_equal :function, value[:type]
|
278
295
|
assert_equal 'ceiling', value[:value]
|
279
|
-
assert_equal
|
296
|
+
assert_equal 'ListPrice', value[:args].first[:value]
|
297
|
+
end
|
298
|
+
|
299
|
+
test 'seconds()' do
|
300
|
+
test_time = Time.new(2019, 4, 1, 8, 30, 20, 0)
|
301
|
+
|
302
|
+
f = FunctionResolver.new('seconds', [{ type: :integer, value: 7 }])
|
303
|
+
f.expects(:current_time).returns(test_time)
|
304
|
+
f.validate
|
305
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
306
|
+
value = f.call
|
307
|
+
|
308
|
+
assert_equal :datetime, value[:type]
|
309
|
+
d = DateTime.parse(value[:value])
|
310
|
+
assert_equal test_time.year, d.year
|
311
|
+
assert_equal test_time.month, d.month
|
312
|
+
assert_equal test_time.mday, d.mday
|
313
|
+
assert_equal test_time.hour, d.hour
|
314
|
+
assert_equal test_time.min, d.min
|
315
|
+
assert_equal test_time.sec + 7, d.sec
|
316
|
+
|
317
|
+
f = FunctionResolver.new('seconds', [{ type: :integer, value: -21 }])
|
318
|
+
f.expects(:current_time).returns(test_time)
|
319
|
+
f.validate
|
320
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
321
|
+
value = f.call
|
322
|
+
|
323
|
+
assert_equal :datetime, value[:type]
|
324
|
+
d = DateTime.parse(value[:value])
|
325
|
+
assert_equal test_time.year, d.year
|
326
|
+
assert_equal test_time.month, d.month
|
327
|
+
assert_equal test_time.mday, d.mday
|
328
|
+
assert_equal test_time.hour, d.hour
|
329
|
+
assert_equal test_time.min - 1, d.min
|
330
|
+
assert_equal 29, d.min
|
331
|
+
assert_equal 59, d.sec
|
332
|
+
|
333
|
+
f = FunctionResolver.new('seconds', [{ type: :integer,
|
334
|
+
value: -Sparkql::FunctionResolver::SECONDS_IN_DAY }])
|
335
|
+
f.expects(:current_time).returns(test_time)
|
336
|
+
f.validate
|
337
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
338
|
+
value = f.call
|
339
|
+
|
340
|
+
assert_equal :datetime, value[:type]
|
341
|
+
d = DateTime.parse(value[:value])
|
342
|
+
assert_equal test_time.year, d.year
|
343
|
+
assert_equal test_time.month - 1, d.month
|
344
|
+
assert_equal 31, d.mday
|
345
|
+
assert_equal test_time.hour, d.hour
|
346
|
+
assert_equal test_time.min, d.min
|
347
|
+
assert_equal test_time.min, d.min
|
348
|
+
assert_equal test_time.sec, d.sec
|
280
349
|
end
|
281
350
|
|
282
|
-
test
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
f
|
351
|
+
test 'minutes()' do
|
352
|
+
test_time = Time.new(2019, 4, 1, 8, 30, 20, 0)
|
353
|
+
|
354
|
+
f = FunctionResolver.new('minutes', [{ type: :integer, value: 7 }])
|
355
|
+
f.expects(:current_time).returns(test_time)
|
356
|
+
f.validate
|
357
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
358
|
+
value = f.call
|
359
|
+
|
360
|
+
assert_equal :datetime, value[:type]
|
361
|
+
d = DateTime.parse(value[:value])
|
362
|
+
assert_equal test_time.year, d.year
|
363
|
+
assert_equal test_time.month, d.month
|
364
|
+
assert_equal test_time.mday, d.mday
|
365
|
+
assert_equal test_time.hour, d.hour
|
366
|
+
assert_equal test_time.min + 7, d.min
|
367
|
+
assert_equal test_time.sec, d.sec
|
368
|
+
|
369
|
+
f = FunctionResolver.new('minutes', [{ type: :integer, value: -37 }])
|
370
|
+
f.expects(:current_time).returns(test_time)
|
371
|
+
f.validate
|
372
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
373
|
+
value = f.call
|
374
|
+
|
375
|
+
assert_equal :datetime, value[:type]
|
376
|
+
d = DateTime.parse(value[:value])
|
377
|
+
assert_equal test_time.year, d.year
|
378
|
+
assert_equal test_time.month, d.month
|
379
|
+
assert_equal test_time.mday, d.mday
|
380
|
+
assert_equal test_time.hour - 1, d.hour
|
381
|
+
assert_equal 53, d.min
|
382
|
+
|
383
|
+
f = FunctionResolver.new('minutes', [{ type: :integer,
|
384
|
+
value: -1440 }])
|
385
|
+
f.expects(:current_time).returns(test_time)
|
386
|
+
f.validate
|
387
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
388
|
+
value = f.call
|
389
|
+
|
390
|
+
assert_equal :datetime, value[:type]
|
391
|
+
d = DateTime.parse(value[:value])
|
392
|
+
assert_equal test_time.year, d.year
|
393
|
+
assert_equal test_time.month - 1, d.month
|
394
|
+
assert_equal 31, d.mday
|
395
|
+
assert_equal test_time.hour, d.hour
|
396
|
+
assert_equal test_time.min, d.min
|
397
|
+
end
|
398
|
+
|
399
|
+
test 'hours(), same day' do
|
400
|
+
test_time = Time.new(2019, 4, 1, 8, 30, 20, 0)
|
401
|
+
tests = [1, -1, 5, -5, 12]
|
402
|
+
|
403
|
+
tests.each do |offset|
|
404
|
+
f = FunctionResolver.new('hours', [{ type: :integer,
|
405
|
+
value: offset }])
|
406
|
+
f.expects(:current_time).returns(test_time)
|
407
|
+
f.validate
|
408
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
409
|
+
value = f.call
|
410
|
+
|
411
|
+
assert_equal :datetime, value[:type]
|
412
|
+
d = DateTime.parse(value[:value])
|
413
|
+
assert_equal test_time.year, d.year
|
414
|
+
assert_equal test_time.month, d.month
|
415
|
+
assert_equal test_time.mday, d.mday
|
416
|
+
assert_equal test_time.hour + offset, d.hour
|
417
|
+
assert_equal test_time.min, d.min
|
418
|
+
assert_equal test_time.sec, d.sec
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
test 'hours(), wrap day' do
|
423
|
+
test_time = Time.new(2019, 4, 1, 8, 30, 20, 0)
|
424
|
+
|
425
|
+
# Jump forward a few days, and a few hours.
|
426
|
+
f = FunctionResolver.new('hours', [{ type: :integer, value: 52 }])
|
427
|
+
f.expects(:current_time).returns(test_time)
|
428
|
+
f.validate
|
429
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
430
|
+
value = f.call
|
431
|
+
|
432
|
+
assert_equal :datetime, value[:type]
|
433
|
+
d = DateTime.parse(value[:value])
|
434
|
+
assert_equal test_time.year, d.year
|
435
|
+
assert_equal test_time.month, d.month
|
436
|
+
assert_equal test_time.mday + 2, d.mday
|
437
|
+
assert_equal test_time.hour + 4, d.hour
|
438
|
+
assert_equal test_time.min, d.min
|
439
|
+
|
440
|
+
# Drop back to the previous day, which'll also hit the previous month
|
441
|
+
f = FunctionResolver.new('hours', [{ type: :integer, value: -24 }])
|
442
|
+
f.expects(:current_time).returns(test_time)
|
443
|
+
f.validate
|
444
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
445
|
+
value = f.call
|
446
|
+
|
447
|
+
assert_equal :datetime, value[:type]
|
448
|
+
d = DateTime.parse(value[:value])
|
449
|
+
assert_equal test_time.year, d.year
|
450
|
+
assert_equal test_time.month - 1, d.month
|
451
|
+
assert_equal 31, d.mday
|
452
|
+
assert_equal test_time.hour, d.hour
|
453
|
+
assert_equal test_time.min, d.min
|
454
|
+
|
455
|
+
# Drop back one full year's worth of hours.
|
456
|
+
f = FunctionResolver.new('hours', [{ type: :integer, value: -8760 }])
|
457
|
+
f.expects(:current_time).returns(test_time)
|
458
|
+
f.validate
|
459
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
460
|
+
value = f.call
|
461
|
+
|
462
|
+
assert_equal :datetime, value[:type]
|
463
|
+
d = DateTime.parse(value[:value])
|
464
|
+
assert_equal test_time.year - 1, d.year
|
465
|
+
assert_equal test_time.month, d.month
|
466
|
+
assert_equal test_time.mday, d.mday
|
467
|
+
assert_equal test_time.hour, d.hour
|
468
|
+
assert_equal test_time.min, d.min
|
469
|
+
end
|
470
|
+
|
471
|
+
test 'days()' do
|
472
|
+
test_date = Date.new(2012, 10, 20) # Sat, 20 Oct 2012 00:00:00 GMT
|
473
|
+
f = FunctionResolver.new('days', [{ type: :integer, value: 7 }])
|
474
|
+
f.expects(:current_date).returns(test_date)
|
288
475
|
f.validate
|
289
476
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
290
477
|
value = f.call
|
291
478
|
assert_equal :date, value[:type]
|
292
|
-
|
293
|
-
|
479
|
+
assert_equal '2012-10-27', value[:value]
|
480
|
+
end
|
481
|
+
|
482
|
+
test 'weekdays()' do
|
483
|
+
friday = Date.new(2012, 10, 19)
|
484
|
+
saturday = Date.new(2012, 10, 20)
|
485
|
+
sunday = Date.new(2012, 10, 21)
|
486
|
+
monday = Date.new(2012, 10, 22)
|
487
|
+
{
|
488
|
+
friday => [
|
489
|
+
[-5, '2012-10-12'],
|
490
|
+
[-4, '2012-10-15'],
|
491
|
+
[-1, '2012-10-18'],
|
492
|
+
[0, '2012-10-19'],
|
493
|
+
[1, '2012-10-22'],
|
494
|
+
[2, '2012-10-23'],
|
495
|
+
[5, '2012-10-26'],
|
496
|
+
[6, '2012-10-29'],
|
497
|
+
[7, '2012-10-30'],
|
498
|
+
[31, '2012-12-03']
|
499
|
+
],
|
500
|
+
saturday => [
|
501
|
+
[-6, '2012-10-12'],
|
502
|
+
[-5, '2012-10-15'],
|
503
|
+
[-1, '2012-10-19'],
|
504
|
+
[0, '2012-10-22'],
|
505
|
+
[1, '2012-10-22'],
|
506
|
+
[2, '2012-10-23'],
|
507
|
+
[3, '2012-10-24'],
|
508
|
+
[4, '2012-10-25'],
|
509
|
+
[5, '2012-10-26'],
|
510
|
+
[6, '2012-10-29'],
|
511
|
+
[7, '2012-10-30'],
|
512
|
+
[31, '2012-12-03']
|
513
|
+
],
|
514
|
+
sunday => [
|
515
|
+
[-6, '2012-10-12'],
|
516
|
+
[-5, '2012-10-15'],
|
517
|
+
[-1, '2012-10-19'],
|
518
|
+
[0, '2012-10-22'],
|
519
|
+
[1, '2012-10-22'],
|
520
|
+
[2, '2012-10-23'],
|
521
|
+
[5, '2012-10-26'],
|
522
|
+
[6, '2012-10-29'],
|
523
|
+
[7, '2012-10-30'],
|
524
|
+
[31, '2012-12-03']
|
525
|
+
],
|
526
|
+
monday => [
|
527
|
+
[-6, '2012-10-12'],
|
528
|
+
[-5, '2012-10-15'],
|
529
|
+
[-1, '2012-10-19'],
|
530
|
+
[0, '2012-10-22'],
|
531
|
+
[1, '2012-10-23'],
|
532
|
+
[2, '2012-10-24'],
|
533
|
+
[5, '2012-10-29'],
|
534
|
+
[6, '2012-10-30'],
|
535
|
+
[7, '2012-10-31'],
|
536
|
+
[31, '2012-12-04']
|
537
|
+
]
|
538
|
+
}.each do |test_date, weekday_tests|
|
539
|
+
weekday_tests.each do |days, expected_value|
|
540
|
+
f = FunctionResolver.new('weekdays', [{ type: :integer, value: days }])
|
541
|
+
f.expects(:current_date).returns(test_date)
|
542
|
+
f.validate
|
543
|
+
assert !f.errors?, "#{test_date}: #{days} = #{expected_value}"
|
544
|
+
value = f.call
|
545
|
+
assert_equal :date, value[:type]
|
546
|
+
assert_equal expected_value, value[:value], "#{test_date}: #{days} = #{expected_value}"
|
547
|
+
end
|
548
|
+
end
|
294
549
|
end
|
295
550
|
|
296
|
-
test
|
551
|
+
test 'months()' do
|
297
552
|
dt = DateTime.new(2014, 1, 6, 0, 0, 0, 0)
|
298
553
|
DateTime.expects(:now).once.returns(dt)
|
299
554
|
|
300
|
-
f = FunctionResolver.new('months', [{:
|
555
|
+
f = FunctionResolver.new('months', [{ type: :integer, value: 3 }])
|
301
556
|
f.validate
|
302
557
|
assert !f.errors?, "Errors resolving months(): #{f.errors.inspect}"
|
303
558
|
value = f.call
|
304
559
|
assert_equal :date, value[:type]
|
305
560
|
|
306
|
-
assert_equal
|
561
|
+
assert_equal '2014-04-06', value[:value]
|
307
562
|
end
|
308
|
-
|
309
|
-
test
|
563
|
+
|
564
|
+
test 'years()' do
|
310
565
|
dt = DateTime.new(2014, 1, 6, 0, 0, 0, 0)
|
311
566
|
DateTime.expects(:now).once.returns(dt)
|
312
|
-
f = FunctionResolver.new('years', [{:
|
567
|
+
f = FunctionResolver.new('years', [{ type: :integer, value: -4 }])
|
313
568
|
f.validate
|
314
569
|
assert !f.errors?, "Errors resolving years(): #{f.errors.inspect}"
|
315
570
|
value = f.call
|
316
571
|
assert_equal :date, value[:type]
|
317
|
-
assert_equal '2010-01-06', value[:value],
|
572
|
+
assert_equal '2010-01-06', value[:value], 'negative values should go back in time'
|
318
573
|
end
|
319
574
|
|
320
|
-
test
|
321
|
-
[
|
322
|
-
f = FunctionResolver.new(function, [{:
|
575
|
+
test 'year(), month(), and day()' do
|
576
|
+
%w[year month day].each do |function|
|
577
|
+
f = FunctionResolver.new(function, [{ type: :field, value: 'OriginalEntryTimestamp' }])
|
323
578
|
f.validate
|
324
579
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
325
580
|
value = f.call
|
326
581
|
assert_equal :function, value[:type]
|
327
582
|
assert_equal function, value[:value]
|
328
|
-
assert_equal
|
583
|
+
assert_equal 'OriginalEntryTimestamp', value[:args].first[:value]
|
329
584
|
end
|
330
585
|
end
|
331
586
|
|
332
|
-
test
|
333
|
-
[
|
334
|
-
f = FunctionResolver.new(function, [{:
|
587
|
+
test 'hour(), minute(), and second()' do
|
588
|
+
%w[year month day].each do |function|
|
589
|
+
f = FunctionResolver.new(function, [{ type: :field, value: 'OriginalEntryTimestamp' }])
|
335
590
|
f.validate
|
336
591
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
337
592
|
value = f.call
|
338
593
|
assert_equal :function, value[:type]
|
339
594
|
assert_equal function, value[:value]
|
340
|
-
assert_equal
|
595
|
+
assert_equal 'OriginalEntryTimestamp', value[:args].first[:value]
|
341
596
|
end
|
342
597
|
end
|
343
598
|
|
344
|
-
test
|
345
|
-
|
599
|
+
test 'day of week and day of year parse' do
|
600
|
+
%w[dayofyear dayofweek].each do |function|
|
601
|
+
f = FunctionResolver.new(function, [{ type: :field, value: 'OriginalEntryTimestamp' }])
|
602
|
+
f.validate
|
603
|
+
assert !f.errors?, "Errors #{f.errors.inspect}"
|
604
|
+
value = f.call
|
605
|
+
assert_equal :function, value[:type]
|
606
|
+
assert_equal function, value[:value]
|
607
|
+
assert_equal 'OriginalEntryTimestamp', value[:args].first[:value]
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
test 'fractionalseconds()' do
|
612
|
+
f = FunctionResolver.new('fractionalseconds', [{ type: :field, value: 'OriginalEntryTimestamp' }])
|
346
613
|
f.validate
|
347
614
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
348
615
|
value = f.call
|
349
616
|
assert_equal :function, value[:type]
|
350
617
|
assert_equal 'fractionalseconds', value[:value]
|
351
|
-
assert_equal
|
618
|
+
assert_equal 'OriginalEntryTimestamp', value[:args].first[:value]
|
352
619
|
end
|
353
620
|
|
354
621
|
# Polygon searches
|
355
|
-
|
356
|
-
test
|
357
|
-
f = FunctionResolver.new('radius',
|
622
|
+
|
623
|
+
test 'radius()' do
|
624
|
+
f = FunctionResolver.new('radius',
|
625
|
+
[{ type: :character, value: '35.12 -68.33' }, { type: :decimal, value: 1.0 }])
|
358
626
|
f.validate
|
359
627
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
360
628
|
value = f.call
|
@@ -364,38 +632,41 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
364
632
|
assert_equal 1.0, value[:value].radius, "#{value[:value].inspect} "
|
365
633
|
end
|
366
634
|
|
367
|
-
test
|
368
|
-
f = FunctionResolver.new('radius', [{:
|
369
|
-
|
635
|
+
test 'radius() can be overloaded with a ListingKey' do
|
636
|
+
f = FunctionResolver.new('radius', [{ type: :character, value: '20100000000000000000000000' },
|
637
|
+
{ type: :decimal, value: 1.0 }])
|
370
638
|
f.validate
|
371
639
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
372
640
|
value = f.call
|
373
641
|
assert_equal :shape, value[:type]
|
374
642
|
assert_equal Sparkql::Geo::RecordRadius, value[:value].class
|
375
|
-
assert_equal
|
643
|
+
assert_equal '20100000000000000000000000', value[:value].record_id, "#{value[:value].inspect} "
|
376
644
|
assert_equal 1.0, value[:value].radius, "#{value[:value].inspect} "
|
377
645
|
end
|
378
646
|
|
379
|
-
test
|
380
|
-
f = FunctionResolver.new('radius', [{:
|
381
|
-
|
647
|
+
test 'radius() fails if not given coords or a flex ID' do
|
648
|
+
f = FunctionResolver.new('radius', [{ type: :character, value: '35.12,-68.33' },
|
649
|
+
{ type: :decimal, value: 1.0 }])
|
382
650
|
f.validate
|
383
651
|
f.call
|
384
652
|
assert f.errors?
|
385
653
|
end
|
386
654
|
|
387
|
-
test
|
388
|
-
f = FunctionResolver.new('polygon',
|
655
|
+
test 'polygon()' do
|
656
|
+
f = FunctionResolver.new('polygon',
|
657
|
+
[{ type: :character,
|
658
|
+
value: '35.12 -68.33,35.12 -68.32, 35.13 -68.32,35.13 -68.33' }])
|
389
659
|
f.validate
|
390
660
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
391
661
|
value = f.call
|
392
662
|
assert_equal :shape, value[:type]
|
393
663
|
assert_equal GeoRuby::SimpleFeatures::Polygon, value[:value].class
|
394
|
-
assert_equal [[-68.33, 35.12], [-68.32, 35.12], [-68.32, 35.13], [-68.33, 35.13], [-68.33, 35.12]],
|
664
|
+
assert_equal [[-68.33, 35.12], [-68.32, 35.12], [-68.32, 35.13], [-68.33, 35.13], [-68.33, 35.12]],
|
665
|
+
value[:value].to_coordinates.first, "#{value[:value].inspect} "
|
395
666
|
end
|
396
|
-
|
397
|
-
test
|
398
|
-
f = FunctionResolver.new('linestring', [{:
|
667
|
+
|
668
|
+
test 'linestring()' do
|
669
|
+
f = FunctionResolver.new('linestring', [{ type: :character, value: '35.12 -68.33,35.12 -68.32' }])
|
399
670
|
f.validate
|
400
671
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
401
672
|
value = f.call
|
@@ -404,70 +675,72 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
404
675
|
assert_equal [[-68.33, 35.12], [-68.32, 35.12]], value[:value].to_coordinates, "#{value[:value].inspect} "
|
405
676
|
end
|
406
677
|
|
407
|
-
test
|
408
|
-
f = FunctionResolver.new('rectangle', [{:
|
678
|
+
test 'rectangle()' do
|
679
|
+
f = FunctionResolver.new('rectangle', [{ type: :character, value: '35.12 -68.33, 35.13 -68.32' }])
|
409
680
|
f.validate
|
410
681
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
411
682
|
value = f.call
|
412
683
|
assert_equal :shape, value[:type]
|
413
684
|
assert_equal GeoRuby::SimpleFeatures::Polygon, value[:value].class
|
414
|
-
assert_equal [[-68.33,35.12], [-68.32,35.12], [-68.32,35.13], [-68.33,35.13], [-68.33,35.12]],
|
685
|
+
assert_equal [[-68.33, 35.12], [-68.32, 35.12], [-68.32, 35.13], [-68.33, 35.13], [-68.33, 35.12]],
|
686
|
+
value[:value].to_coordinates.first, "#{value[:value].inspect} "
|
415
687
|
end
|
416
688
|
|
417
|
-
test
|
418
|
-
f = FunctionResolver.new('range', [{:
|
419
|
-
|
689
|
+
test 'range()' do
|
690
|
+
f = FunctionResolver.new('range', [{ type: :character, value: 'M01' },
|
691
|
+
{ type: :character, value: 'M05' }])
|
420
692
|
f.validate
|
421
693
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
422
694
|
value = f.call
|
423
695
|
assert_equal :character, value[:type]
|
424
|
-
assert_equal [
|
696
|
+
assert_equal %w[M01 M05], value[:value]
|
425
697
|
end
|
426
|
-
|
427
|
-
test
|
428
|
-
f = FunctionResolver.new('now', [{:
|
698
|
+
|
699
|
+
test 'invalid params' do
|
700
|
+
f = FunctionResolver.new('now', [{ type: :character, value: 'bad value' }])
|
429
701
|
f.validate
|
430
702
|
assert f.errors?, "'now' function does not support parameters"
|
431
|
-
|
703
|
+
|
432
704
|
f = FunctionResolver.new('days', [])
|
433
705
|
f.validate
|
434
706
|
assert f.errors?, "'days' function requires one parameter"
|
435
|
-
|
436
|
-
f = FunctionResolver.new('days', [{:
|
707
|
+
|
708
|
+
f = FunctionResolver.new('days', [{ type: :character, value: 'bad value' }])
|
437
709
|
f.validate
|
438
710
|
assert f.errors?, "'days' function needs integer parameter"
|
439
711
|
end
|
440
712
|
|
441
|
-
test
|
442
|
-
f = FunctionResolver.new('radius', [{:
|
443
|
-
|
444
|
-
|
713
|
+
test 'assert nil returned when function called with errors' do
|
714
|
+
f = FunctionResolver.new('radius', [{ type: :character,
|
715
|
+
value: '35.12 -68.33, 35.13 -68.34' }, { type: :decimal,
|
716
|
+
value: 1.0 }])
|
445
717
|
assert_nil f.call
|
446
718
|
end
|
447
|
-
|
448
|
-
test
|
449
|
-
f = FunctionResolver.new('radius', [{:
|
450
|
-
|
451
|
-
|
719
|
+
|
720
|
+
test 'return_type' do
|
721
|
+
f = FunctionResolver.new('radius', [{ type: :character,
|
722
|
+
value: '35.12 -68.33, 35.13 -68.34' }, { type: :decimal,
|
723
|
+
value: 1.0 }])
|
452
724
|
assert_equal :shape, f.return_type
|
453
725
|
end
|
454
726
|
|
455
727
|
test 'return_type for cast()' do
|
456
|
-
f = FunctionResolver.new('cast', [{:
|
457
|
-
|
458
|
-
|
728
|
+
f = FunctionResolver.new('cast', [{ type: :character,
|
729
|
+
value: '1' }, { type: :character,
|
730
|
+
value: 'decimal' }])
|
459
731
|
|
460
732
|
assert_equal :decimal, f.return_type
|
461
733
|
|
462
|
-
f = FunctionResolver.new('cast', [{:
|
463
|
-
|
464
|
-
|
734
|
+
f = FunctionResolver.new('cast', [{ type: :character,
|
735
|
+
value: '1' }, { type: :character,
|
736
|
+
value: 'integer' }])
|
465
737
|
|
466
738
|
assert_equal :integer, f.return_type
|
467
739
|
end
|
468
740
|
|
469
|
-
test
|
470
|
-
f = FunctionResolver.new('cast',
|
741
|
+
test 'cast() decimal to integer' do
|
742
|
+
f = FunctionResolver.new('cast',
|
743
|
+
[{ type: :decimal, value: '1.2' }, { type: :character, value: 'integer' }])
|
471
744
|
f.validate
|
472
745
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
473
746
|
value = f.call
|
@@ -476,8 +749,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
476
749
|
assert_equal '1', value[:value]
|
477
750
|
end
|
478
751
|
|
479
|
-
test
|
480
|
-
f = FunctionResolver.new('cast', [{:
|
752
|
+
test 'cast() integer to decimal' do
|
753
|
+
f = FunctionResolver.new('cast', [{ type: :decimal, value: '1' }, { type: :character, value: 'decimal' }])
|
481
754
|
f.validate
|
482
755
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
483
756
|
value = f.call
|
@@ -486,8 +759,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
486
759
|
assert_equal '1.0', value[:value]
|
487
760
|
end
|
488
761
|
|
489
|
-
test
|
490
|
-
f = FunctionResolver.new('cast', [{:
|
762
|
+
test 'cast() nil to integer' do
|
763
|
+
f = FunctionResolver.new('cast', [{ type: :null, value: 'NULL' }, { type: :character, value: 'integer' }])
|
491
764
|
f.validate
|
492
765
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
493
766
|
value = f.call
|
@@ -496,8 +769,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
496
769
|
assert_equal '0', value[:value]
|
497
770
|
end
|
498
771
|
|
499
|
-
test
|
500
|
-
f = FunctionResolver.new('cast', [{:
|
772
|
+
test 'cast() nil to decimal' do
|
773
|
+
f = FunctionResolver.new('cast', [{ type: :null, value: 'NULL' }, { type: :character, value: 'decimal' }])
|
501
774
|
f.validate
|
502
775
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
503
776
|
value = f.call
|
@@ -506,8 +779,9 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
506
779
|
assert_equal '0.0', value[:value]
|
507
780
|
end
|
508
781
|
|
509
|
-
test
|
510
|
-
f = FunctionResolver.new('cast',
|
782
|
+
test 'cast() nil to character' do
|
783
|
+
f = FunctionResolver.new('cast',
|
784
|
+
[{ type: :null, value: 'NULL' }, { type: :character, value: 'character' }])
|
511
785
|
f.validate
|
512
786
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
513
787
|
value = f.call
|
@@ -516,39 +790,43 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
516
790
|
assert_equal "''", value[:value]
|
517
791
|
end
|
518
792
|
|
519
|
-
test
|
520
|
-
f = FunctionResolver.new('cast',
|
793
|
+
test 'cast() character to decimal' do
|
794
|
+
f = FunctionResolver.new('cast',
|
795
|
+
[{ type: :character, value: '1.1' }, { type: :character, value: 'decimal' }])
|
521
796
|
f.validate
|
522
797
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
523
798
|
value = f.call
|
524
799
|
|
525
800
|
assert_equal :decimal, value[:type]
|
526
|
-
assert_equal
|
801
|
+
assert_equal '1.1', value[:value]
|
527
802
|
end
|
528
803
|
|
529
|
-
test
|
530
|
-
f = FunctionResolver.new('cast',
|
804
|
+
test 'cast() character to integer' do
|
805
|
+
f = FunctionResolver.new('cast',
|
806
|
+
[{ type: :character, value: '1' }, { type: :character, value: 'integer' }])
|
531
807
|
f.validate
|
532
808
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
533
809
|
value = f.call
|
534
810
|
|
535
811
|
assert_equal :integer, value[:type]
|
536
|
-
assert_equal
|
812
|
+
assert_equal '1', value[:value]
|
537
813
|
end
|
538
814
|
|
539
|
-
test
|
540
|
-
f = FunctionResolver.new('cast',
|
815
|
+
test 'cast() Field' do
|
816
|
+
f = FunctionResolver.new('cast',
|
817
|
+
[{ type: :field, value: 'Bedrooms' }, { type: :character, value: 'character' }])
|
541
818
|
f.validate
|
542
819
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
543
820
|
value = f.call
|
544
821
|
|
545
822
|
assert_equal :function, value[:type]
|
546
823
|
assert_equal 'cast', value[:value]
|
547
|
-
assert_equal
|
824
|
+
assert_equal(%w[Bedrooms character], value[:args].map{ |v| v[:value] })
|
548
825
|
end
|
549
826
|
|
550
|
-
test
|
551
|
-
f = FunctionResolver.new('cast',
|
827
|
+
test 'invalid cast returns null' do
|
828
|
+
f = FunctionResolver.new('cast',
|
829
|
+
[{ type: :character, value: '1.1.1' }, { type: :character, value: 'integer' }])
|
552
830
|
f.validate
|
553
831
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
554
832
|
value = f.call
|
@@ -557,14 +835,14 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
557
835
|
assert_equal 'NULL', value[:value]
|
558
836
|
end
|
559
837
|
|
560
|
-
test
|
838
|
+
test 'invalid function' do
|
561
839
|
f = FunctionResolver.new('then', [])
|
562
840
|
f.validate
|
563
841
|
assert f.errors?, "'then' is not a function"
|
564
842
|
end
|
565
843
|
|
566
|
-
test
|
567
|
-
f = FunctionResolver.new('time', [{:
|
844
|
+
test 'time(datetime)' do
|
845
|
+
f = FunctionResolver.new('time', [{ type: :datetime, value: EXAMPLE_DATE }])
|
568
846
|
f.validate
|
569
847
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
570
848
|
value = f.call
|
@@ -572,8 +850,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
572
850
|
assert_equal '10:22:15.422804000', value[:value]
|
573
851
|
end
|
574
852
|
|
575
|
-
test
|
576
|
-
f = FunctionResolver.new('date', [{:
|
853
|
+
test 'date(datetime)' do
|
854
|
+
f = FunctionResolver.new('date', [{ type: :datetime, value: EXAMPLE_DATE }])
|
577
855
|
f.validate
|
578
856
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
579
857
|
value = f.call
|
@@ -581,39 +859,39 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
581
859
|
assert_equal '2013-07-26', value[:value]
|
582
860
|
end
|
583
861
|
|
584
|
-
###
|
585
|
-
# Delayed functions. These functions don't get run immediately and require
|
586
|
-
# resolution by the backing system
|
587
|
-
###
|
588
|
-
|
589
|
-
test
|
590
|
-
f = FunctionResolver.new('time', [{:
|
862
|
+
###
|
863
|
+
# Delayed functions. These functions don't get run immediately and require
|
864
|
+
# resolution by the backing system
|
865
|
+
###
|
866
|
+
|
867
|
+
test 'time(field)' do
|
868
|
+
f = FunctionResolver.new('time', [{ type: :field, value: 'OriginalEntryTimestamp' }])
|
591
869
|
f.validate
|
592
870
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
593
871
|
value = f.call
|
594
872
|
assert_equal :function, value[:type]
|
595
873
|
assert_equal 'time', value[:value]
|
596
|
-
assert_equal
|
874
|
+
assert_equal 'OriginalEntryTimestamp', value[:args].first[:value]
|
597
875
|
end
|
598
|
-
|
599
|
-
test
|
600
|
-
f = FunctionResolver.new('date', [{:
|
876
|
+
|
877
|
+
test 'date(field)' do
|
878
|
+
f = FunctionResolver.new('date', [{ type: :field, value: 'OriginalEntryTimestamp' }])
|
601
879
|
f.validate
|
602
880
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
603
881
|
value = f.call
|
604
882
|
assert_equal :function, value[:type]
|
605
883
|
assert_equal 'date', value[:value]
|
606
|
-
assert_equal
|
884
|
+
assert_equal 'OriginalEntryTimestamp', value[:args].first[:value]
|
607
885
|
end
|
608
886
|
|
609
|
-
test
|
610
|
-
[{'startswith' =>
|
611
|
-
{'endswith' =>
|
612
|
-
{'contains' =>
|
887
|
+
test 'startswith(), endswith() and contains()' do
|
888
|
+
[{ 'startswith' => '^far' },
|
889
|
+
{ 'endswith' => 'far$' },
|
890
|
+
{ 'contains' => 'far' }].each do |test_case|
|
613
891
|
function = test_case.keys.first
|
614
892
|
expected_value = test_case[function]
|
615
893
|
|
616
|
-
f = FunctionResolver.new(function, [{:
|
894
|
+
f = FunctionResolver.new(function, [{ type: :character, value: 'far' }])
|
617
895
|
f.validate
|
618
896
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
619
897
|
value = f.call
|
@@ -626,8 +904,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
626
904
|
|
627
905
|
test 'wkt()' do
|
628
906
|
f = FunctionResolver.new('wkt',
|
629
|
-
[{:
|
630
|
-
|
907
|
+
[{ type: :character,
|
908
|
+
value: 'SRID=12345;POLYGON((-127.89734578345 45.234534534,-127.89734578345 45.234534534,-127.89734578345 45.234534534,-127.89734578345 45.234534534))' }])
|
631
909
|
f.validate
|
632
910
|
assert !f.errors?, "Errors #{f.errors.inspect}"
|
633
911
|
value = f.call
|
@@ -636,8 +914,8 @@ class FunctionResolverTest < Test::Unit::TestCase
|
|
636
914
|
|
637
915
|
test 'wkt() invalid params' do
|
638
916
|
f = FunctionResolver.new('wkt',
|
639
|
-
[{:
|
640
|
-
|
917
|
+
[{ type: :character,
|
918
|
+
value: 'POLYGON((45.234534534))' }])
|
641
919
|
f.validate
|
642
920
|
f.call
|
643
921
|
assert f.errors?
|