sparkql 1.2.4 → 1.2.8
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 +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?
|