sparkql 1.1.17 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,7 +31,7 @@ class FunctionResolverTest < Test::Unit::TestCase
31
31
 
32
32
  assert_equal :function, value[:type]
33
33
  assert_equal 'round', value[:value]
34
- assert_equal "ListPrice", value[:args].first
34
+ assert_equal "ListPrice", value[:args].first[:value]
35
35
  end
36
36
 
37
37
  test "substring character one index" do
@@ -89,8 +89,8 @@ class FunctionResolverTest < Test::Unit::TestCase
89
89
 
90
90
  assert_equal :function, value[:type]
91
91
  assert_equal 'substring', value[:value]
92
- assert_equal "ListPrice", value[:args].first
93
- assert_nil value[:args].last
92
+ assert_equal "ListPrice", value[:args].first[:value]
93
+ assert_equal 2, value[:args].size
94
94
  end
95
95
 
96
96
  test "substring field two indexes" do
@@ -106,8 +106,8 @@ class FunctionResolverTest < Test::Unit::TestCase
106
106
 
107
107
  assert_equal :function, value[:type]
108
108
  assert_equal 'substring', value[:value]
109
- assert_equal "ListPrice", value[:args].first
110
- assert_equal 2, value[:args].last
109
+ assert_equal "ListPrice", value[:args].first[:value]
110
+ assert_equal 2, value[:args].last[:value]
111
111
  end
112
112
 
113
113
  test "substring with negative M is a parse error" do
@@ -145,7 +145,7 @@ class FunctionResolverTest < Test::Unit::TestCase
145
145
 
146
146
  assert_equal :function, value[:type]
147
147
  assert_equal 'trim', value[:value]
148
- assert_equal "Name", value[:args].first
148
+ assert_equal "Name", value[:args].first[:value]
149
149
  end
150
150
 
151
151
  test 'trim with character' do
@@ -177,7 +177,7 @@ class FunctionResolverTest < Test::Unit::TestCase
177
177
  value = f.call
178
178
  assert_equal :function, value[:type]
179
179
  assert_equal 'toupper', value[:value]
180
- assert_equal "City", value[:args].first
180
+ assert_equal "City", value[:args].first[:value]
181
181
  end
182
182
 
183
183
  test "toupper('string')" do
@@ -196,7 +196,7 @@ class FunctionResolverTest < Test::Unit::TestCase
196
196
  value = f.call
197
197
  assert_equal :function, value[:type]
198
198
  assert_equal 'length', value[:value]
199
- assert_equal "City", value[:args].first
199
+ assert_equal "City", value[:args].first[:value]
200
200
  end
201
201
 
202
202
  test "length('string')" do
@@ -256,7 +256,7 @@ class FunctionResolverTest < Test::Unit::TestCase
256
256
 
257
257
  assert_equal :function, value[:type]
258
258
  assert_equal 'floor', value[:value]
259
- assert_equal "ListPrice", value[:args].first
259
+ assert_equal "ListPrice", value[:args].first[:value]
260
260
  end
261
261
 
262
262
  test "ceiling(float)" do
@@ -276,7 +276,7 @@ class FunctionResolverTest < Test::Unit::TestCase
276
276
 
277
277
  assert_equal :function, value[:type]
278
278
  assert_equal 'ceiling', value[:value]
279
- assert_equal "ListPrice", value[:args].first
279
+ assert_equal "ListPrice", value[:args].first[:value]
280
280
  end
281
281
 
282
282
  test "days()" do
@@ -325,7 +325,7 @@ class FunctionResolverTest < Test::Unit::TestCase
325
325
  value = f.call
326
326
  assert_equal :function, value[:type]
327
327
  assert_equal function, value[:value]
328
- assert_equal "OriginalEntryTimestamp", value[:args].first
328
+ assert_equal "OriginalEntryTimestamp", value[:args].first[:value]
329
329
  end
330
330
  end
331
331
 
@@ -337,7 +337,7 @@ class FunctionResolverTest < Test::Unit::TestCase
337
337
  value = f.call
338
338
  assert_equal :function, value[:type]
339
339
  assert_equal function, value[:value]
340
- assert_equal "OriginalEntryTimestamp", value[:args].first
340
+ assert_equal "OriginalEntryTimestamp", value[:args].first[:value]
341
341
  end
342
342
  end
343
343
 
@@ -348,7 +348,7 @@ class FunctionResolverTest < Test::Unit::TestCase
348
348
  value = f.call
349
349
  assert_equal :function, value[:type]
350
350
  assert_equal 'fractionalseconds', value[:value]
351
- assert_equal "OriginalEntryTimestamp", value[:args].first
351
+ assert_equal "OriginalEntryTimestamp", value[:args].first[:value]
352
352
  end
353
353
 
354
354
  # Polygon searches
@@ -544,7 +544,7 @@ class FunctionResolverTest < Test::Unit::TestCase
544
544
 
545
545
  assert_equal :function, value[:type]
546
546
  assert_equal 'cast', value[:value]
547
- assert_equal ['Bedrooms', 'character'], value[:args]
547
+ assert_equal ['Bedrooms', 'character'], value[:args].map { |v| v[:value]}
548
548
  end
549
549
 
550
550
  test "invalid cast returns null" do
@@ -593,7 +593,7 @@ class FunctionResolverTest < Test::Unit::TestCase
593
593
  value = f.call
594
594
  assert_equal :function, value[:type]
595
595
  assert_equal 'time', value[:value]
596
- assert_equal "OriginalEntryTimestamp", value[:args].first
596
+ assert_equal "OriginalEntryTimestamp", value[:args].first[:value]
597
597
  end
598
598
 
599
599
  test "date(field)" do
@@ -603,7 +603,7 @@ class FunctionResolverTest < Test::Unit::TestCase
603
603
  value = f.call
604
604
  assert_equal :function, value[:type]
605
605
  assert_equal 'date', value[:value]
606
- assert_equal "OriginalEntryTimestamp", value[:args].first
606
+ assert_equal "OriginalEntryTimestamp", value[:args].first[:value]
607
607
  end
608
608
 
609
609
  test "startswith(), endswith() and contains()" do
@@ -346,6 +346,23 @@ class ParserCompatabilityTest < Test::Unit::TestCase
346
346
  assert parser.errors?
347
347
  end
348
348
 
349
+ test "max out nested functions of 5" do
350
+ field = "tolower(City)"
351
+
352
+ 4.times do
353
+ field = "tolower(#{field})"
354
+ end
355
+
356
+ parser = Parser.new
357
+ parser.parse("#{field} Eq 'Fargo'")
358
+ assert !parser.errors?
359
+
360
+ parser = Parser.new
361
+ field = "tolower(#{field})"
362
+ parser.parse("#{field} Eq 'Fargo'")
363
+ assert parser.errors?, 'should error on too many nested functions'
364
+ end
365
+
349
366
  test "max out function args" do
350
367
  parser = Parser.new
351
368
  to_the_max = []
@@ -170,6 +170,11 @@ class ParserTest < Test::Unit::TestCase
170
170
  assert_equal 'City', expression[:field]
171
171
  assert_equal '13', expression[:value]
172
172
  assert_equal '4131800000000', expression[:args].last
173
+
174
+ assert_equal 'indexof', expression[:field_manipulations][:function_name]
175
+ assert_equal :function, expression[:field_manipulations][:type]
176
+ assert_equal :integer, expression[:field_manipulations][:return_type]
177
+ assert_equal ['City', '4131800000000'], expression[:field_manipulations][:args].map {|v| v[:value]}
173
178
  end
174
179
 
175
180
  test "function data preserved in expression" do
@@ -207,8 +212,6 @@ class ParserTest < Test::Unit::TestCase
207
212
  end
208
213
 
209
214
  test "mixed list" do
210
- # TODO This is an unrealistic example. We need number functions or support
211
- # for dates in lists
212
215
  filter = "OriginalEntryTimestamp Eq 2014,days(-7)"
213
216
  @parser = Parser.new
214
217
  expressions = @parser.parse(filter)
@@ -217,14 +220,11 @@ class ParserTest < Test::Unit::TestCase
217
220
  assert_equal '2014,days(-7)', expressions.first[:condition]
218
221
  end
219
222
 
223
+ def test_errors_on_left_hand_field_function
224
+ parser_errors("Field Eq ceiling(Field)")
225
+ end
226
+
220
227
  def test_function_date
221
- filter = "OnMarketDate Eq date(OriginalEntryTimestamp)"
222
- @parser = Parser.new
223
- expressions = @parser.parse(filter)
224
- assert !@parser.errors?, "errors #{@parser.errors.inspect}"
225
- assert_equal 'date(OriginalEntryTimestamp)', expressions.first[:condition]
226
- assert_equal 'date', expressions.first[:value]
227
- assert_equal :function, expressions.first[:type]
228
228
  # Run using a static value, we just resolve the type
229
229
  filter = "OnMarketDate Eq date(2013-07-26T10:22:15.111-0100)"
230
230
  @parser = Parser.new
@@ -685,14 +685,17 @@ class ParserTest < Test::Unit::TestCase
685
685
  end
686
686
 
687
687
  def test_round_with_field
688
- filter = "ListPrice Eq round(FieldName)"
688
+ filter = "round(ListPrice) Eq 1"
689
689
  @parser = Parser.new
690
690
  expression = @parser.parse(filter).first
691
691
  assert !@parser.errors?, "Filter '#{filter}' failed: #{@parser.errors.first.inspect}"
692
692
 
693
- assert_equal 'round', expression[:function_name]
694
- assert_equal 'round(FieldName)', expression[:condition]
695
- assert_equal(["FieldName"], expression[:function_parameters])
693
+ assert_equal 'round', expression[:field_function]
694
+ assert_equal(["ListPrice"], expression[:args])
695
+
696
+ assert_equal 'round', expression[:field_manipulations][:function_name]
697
+ assert_equal :function, expression[:field_manipulations][:type]
698
+ assert_equal ['ListPrice'], expression[:field_manipulations][:args].map {|v| v[:value]}
696
699
  end
697
700
 
698
701
  def test_ceiling_with_literal
@@ -714,14 +717,13 @@ class ParserTest < Test::Unit::TestCase
714
717
  end
715
718
 
716
719
  def test_ceiling_with_field
717
- filter = "ListPrice Eq ceiling(FieldName)"
720
+ filter = "ceiling(ListPrice) Eq 4"
718
721
  @parser = Parser.new
719
722
  expression = @parser.parse(filter).first
720
723
  assert !@parser.errors?, "Filter '#{filter}' failed: #{@parser.errors.first.inspect}"
721
724
 
722
- assert_equal 'ceiling', expression[:function_name]
723
- assert_equal 'ceiling(FieldName)', expression[:condition]
724
- assert_equal(["FieldName"], expression[:function_parameters])
725
+ assert_equal 'ceiling', expression[:field_function]
726
+ assert_equal(["ListPrice"], expression[:args])
725
727
  end
726
728
 
727
729
  def test_floor_with_literal
@@ -743,26 +745,33 @@ class ParserTest < Test::Unit::TestCase
743
745
  end
744
746
 
745
747
  def test_floor_with_field
746
- filter = "ListPrice Eq floor(FieldName)"
748
+ filter = "floor(ListPrice) Eq 1"
747
749
  @parser = Parser.new
748
750
  expression = @parser.parse(filter).first
749
751
  assert !@parser.errors?, "Filter '#{filter}' failed: #{@parser.errors.first.inspect}"
750
752
 
751
- assert_equal 'floor', expression[:function_name]
752
- assert_equal 'floor(FieldName)', expression[:condition]
753
- assert_equal(["FieldName"], expression[:function_parameters])
753
+ assert_equal 'floor', expression[:field_function]
754
+ assert_equal(["ListPrice"], expression[:args])
755
+
756
+ assert_equal 'floor', expression[:field_manipulations][:function_name]
757
+ assert_equal :function, expression[:field_manipulations][:type]
758
+ assert_equal ['ListPrice'], expression[:field_manipulations][:args].map {|v| v[:value]}
754
759
  end
755
760
 
756
761
  def test_concat_with_field
757
- filter = "City Eq concat(City, 'b')"
762
+ filter = "concat(City, 'b') Eq 'Fargob'"
758
763
  @parser = Parser.new
759
764
  expression = @parser.parse(filter).first
760
765
  assert !@parser.errors?, "Filter '#{filter}' failed: #{@parser.errors.first.inspect}"
761
766
 
762
- assert_equal :function, expression[:type]
763
- assert_equal 'concat', expression[:function_name]
764
- assert_equal(["City", 'b'], expression[:function_parameters])
767
+ assert_equal :character, expression[:type]
768
+ assert_equal 'concat', expression[:field_function]
769
+ assert_equal(["City", 'b'], expression[:args])
765
770
  assert_equal("City", expression[:field])
771
+
772
+ assert_equal 'concat', expression[:field_manipulations][:function_name]
773
+ assert_equal :function, expression[:field_manipulations][:type]
774
+ assert_equal ['City', 'b'], expression[:field_manipulations][:args].map {|v| v[:value]}
766
775
  end
767
776
 
768
777
  def test_concat_with_literal
@@ -786,6 +795,10 @@ class ParserTest < Test::Unit::TestCase
786
795
  assert_equal 'cast', expression[:field_function]
787
796
  assert_equal "'100000'", expression[:condition]
788
797
  assert_equal(:character, expression[:field_function_type])
798
+
799
+ assert_equal 'cast', expression[:field_manipulations][:function_name]
800
+ assert_equal :function, expression[:field_manipulations][:type]
801
+ assert_equal ['ListPrice', 'character'], expression[:field_manipulations][:args].map {|v| v[:value]}
789
802
  end
790
803
 
791
804
  def test_cast_with_invalid_type
@@ -793,6 +806,39 @@ class ParserTest < Test::Unit::TestCase
793
806
  parser_errors("ListPrice Eq cast('10', 'bogus')")
794
807
  end
795
808
 
809
+ test 'nested functions on field side' do
810
+ @parser = Parser.new
811
+ filter = "tolower(toupper(City)) Eq 'Fargo'"
812
+ expression = @parser.parse(filter).first
813
+ assert_equal 'City', expression[:field]
814
+ assert expression.key?(:field_manipulations)
815
+ function1 = expression[:field_manipulations]
816
+ assert_equal :function, function1[:type]
817
+ assert_equal 'tolower', function1[:function_name]
818
+ assert_equal 'tolower', expression[:field_function]
819
+
820
+ function2 = function1[:args].first
821
+ assert_equal :function, function2[:type]
822
+ assert_equal 'toupper', function2[:function_name]
823
+ assert_equal({:type=>:field, :value=>"City"}, function2[:args].first)
824
+ end
825
+
826
+ test 'nested functions with multiple params' do
827
+ filter = "concat(tolower(City), 'b') Eq 'fargob'"
828
+ @parser = Parser.new
829
+ expression = @parser.parse(filter).first
830
+ assert expression.key?(:field_manipulations)
831
+ function1 = expression[:field_manipulations]
832
+ assert_equal :function, function1[:type]
833
+ assert_equal 'concat', function1[:function_name]
834
+ assert_equal({type: :character, value: 'b'}, function1[:args].last)
835
+
836
+ function2 = function1[:args].first
837
+ assert_equal :function, function2[:type]
838
+ assert_equal 'tolower', function2[:function_name]
839
+ assert_equal({:type=>:field, :value=>"City"}, function2[:args].first)
840
+ end
841
+
796
842
  private
797
843
 
798
844
  def parser_errors(filter)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparkql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.17
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wade McEwen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-02 00:00:00.000000000 Z
11
+ date: 2018-09-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: georuby