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