sparkql 1.1.17 → 1.2.0

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.
@@ -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