Skip to content

Commit b685896

Browse files
committed
Merge pull request #35 from wlmcewen/API-3785
API-3785 date and time function support on fields and datetime values
2 parents c20803c + 27d8b20 commit b685896

17 files changed

+359
-122
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
v1.0.0, 2016-02-11 ([changes](https://github.com/sparkapi/sparkql/compare/v0.3.20...v1.0.0))
2+
-------------------
3+
* [IMPROVEMENT] function support for fields (delayed resolution). Backing systems must
4+
implement necessary function behaviour.
5+
* Drop support for ruby 1.8.7. Georuby dropped support several years back and
6+
this drop allows us to pick up newer update allows us to stay in sync with
7+
that gems development
8+
19
v0.3.24, 2016-01-05 ([changes](https://github.com/sparkapi/sparkql/compare/v0.3.23...v0.3.24))
210
-------------------
311

GRAMMAR.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ filter.
9494
field
9595
: STANDARD_FIELD
9696
| CUSTOM_FIELD
97+
| function
9798
;
9899
```
99100

@@ -140,6 +141,7 @@ Functions may optionally have a comma delimited list of parameters.
140141
function_arg
141142
: literal
142143
| literals
144+
| field
143145
;
144146
```
145147

@@ -187,6 +189,7 @@ Literals only support a single value in a condition
187189
literal
188190
: DATE
189191
| DATETIME
192+
| TIME
190193
| BOOLEAN
191194
| NULL
192195
;
@@ -202,6 +205,7 @@ Functions, and literals that can be used in a range
202205
| DECIMAL
203206
| DATE
204207
| DATETIME
208+
| TIME
205209
| function
206210
;
207211
```

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
source "http://gems.flexmls.com/"
21
source "http://rubygems.org"
32

43
# Specify your gem's dependencies in sparkapi_parser.gemspec

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
SparkQL query language parser
22
=====================
3-
This gem contains the syntax parser for processing spark api filter queries into manageable
3+
This gem contains the syntax parser for processing spark api filter queries into manageable
44
expressions. To get an overview of the language syntax-wise, refer to the following files:
55

66
* lib/sparkql/parser.y # BNF Grammar
@@ -12,14 +12,16 @@ Installation
1212
Add the gem to your gemfile:
1313

1414
Gemfile
15-
gem 'sparkql', '~> 0.0.1'
15+
gem 'sparkql', '~> 0.0.1'
1616

1717
When completed, run 'bundle install'.
1818

1919

2020
Usage
2121
-------------
22-
See test/unit/parser_test.rb for generic parsing examples. In most cases an extended parser is
22+
Ruby 1.9 or greater is required.
23+
24+
See test/unit/parser_test.rb for generic parsing examples. In most cases an extended parser is
2325
needed to do anything of significance, such as the postgres and db2 search implementations in the
2426
API.
2527

@@ -40,12 +42,12 @@ The return value will be an array with one expression element containing the que
4042

4143
Development
4244
-------------
43-
The parser is based on racc, a yacc like LR parser that is a part of the ruby runtime. The grammar
44-
is located at lib/sparkql/parser.y and is compiled as part of the test process. Refer to the
45-
Rakefile for details. When modifying the grammar, please checkin BOTH the parser.y and parser.rb
45+
The parser is based on racc, a yacc like LR parser that is a part of the ruby runtime. The grammar
46+
is located at lib/sparkql/parser.y and is compiled as part of the test process. Refer to the
47+
Rakefile for details. When modifying the grammar, please checkin BOTH the parser.y and parser.rb
4648
files.
4749

48-
Debugging grammar issues can be done by hand using the "racc" command. For example, a dump of the
50+
Debugging grammar issues can be done by hand using the "racc" command. For example, a dump of the
4951
parser states (and conflicts) can be generated via
5052

5153
racc -o lib/sparkql/parser.rb lib/sparkql/parser.y -v # see lib/sparkql/parser.output

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.3.24
1+
1.0.0

lib/sparkql/function_resolver.rb

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
# SUPPORTED_FUNCTIONS which will run validation on the function syntax prior to execution.
1111
class Sparkql::FunctionResolver
1212
SECONDS_IN_DAY = 60 * 60 * 24
13-
STRFTIME_FORMAT = '%Y-%m-%d'
14-
13+
STRFTIME_DATE_FORMAT = '%Y-%m-%d'
14+
STRFTIME_TIME_FORMAT = '%H:%M:%S.%N'
1515
VALID_REGEX_FLAGS = ["", "i"]
1616
SUPPORTED_FUNCTIONS = {
1717
:polygon => {
@@ -53,6 +53,16 @@ class Sparkql::FunctionResolver
5353
:now => {
5454
:args => [],
5555
:return_type => :datetime
56+
},
57+
:date => {
58+
:args => [[:field,:datetime]],
59+
:resolve_for_type => true,
60+
:return_type => :date
61+
},
62+
:time => {
63+
:args => [[:field,:datetime]],
64+
:resolve_for_type => true,
65+
:return_type => :time
5666
}
5767
}
5868

@@ -89,7 +99,7 @@ def validate()
8999

90100
count = 0
91101
@args.each do |arg|
92-
unless arg[:type] == total_args[count]
102+
unless Array(total_args[count]).include?(arg[:type])
93103
@errors << Sparkql::ParserError.new(:token => @name,
94104
:message => "Function call '#{@name}' has an invalid argument at #{arg[:value]}",
95105
:status => :fatal )
@@ -99,7 +109,7 @@ def validate()
99109
end
100110

101111
def return_type
102-
supported[@name.to_sym][:return_type]
112+
support[@name.to_sym][:return_type]
103113
end
104114

105115
def errors
@@ -126,8 +136,12 @@ def call()
126136
fill_in_optional_args.each do |default|
127137
real_vals << default
128138
end
129-
130-
v = self.send(name, *real_vals)
139+
method = name
140+
if support[name][:resolve_for_type]
141+
method_type = @args.first[:type]
142+
method = "#{method}_#{method_type}"
143+
end
144+
v = self.send(method, *real_vals)
131145

132146
unless v.nil?
133147
v[:function_name] = @name
@@ -172,7 +186,7 @@ def days(num)
172186
d = Date.today + num
173187
{
174188
:type => :date,
175-
:value => d.strftime(STRFTIME_FORMAT)
189+
:value => d.strftime(STRFTIME_DATE_FORMAT)
176190
}
177191
end
178192

@@ -183,20 +197,50 @@ def now()
183197
:value => Time.now.iso8601
184198
}
185199
end
200+
201+
def date_field(arg)
202+
{
203+
:type => :function,
204+
:value => "date",
205+
:args => [arg]
206+
}
207+
end
208+
209+
def time_field(arg)
210+
{
211+
:type => :function,
212+
:value => "time",
213+
:args => [arg]
214+
}
215+
end
216+
217+
def date_datetime(dt)
218+
{
219+
:type => :date,
220+
:value => dt.strftime(STRFTIME_DATE_FORMAT)
221+
}
222+
end
223+
224+
def time_datetime(dt)
225+
{
226+
:type => :time,
227+
:value => dt.strftime(STRFTIME_TIME_FORMAT)
228+
}
229+
end
186230

187231
def months num_months
188232
d = DateTime.now >> num_months
189233
{
190234
:type => :date,
191-
:value => d.strftime(STRFTIME_FORMAT)
235+
:value => d.strftime(STRFTIME_DATE_FORMAT)
192236
}
193237
end
194238

195239
def years num_years
196240
d = DateTime.now >> (num_years * 12)
197241
{
198242
:type => :date,
199-
:value => d.strftime(STRFTIME_FORMAT)
243+
:value => d.strftime(STRFTIME_DATE_FORMAT)
200244
}
201245
end
202246

lib/sparkql/lexer.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ def shift
3939
literal :DATETIME, @current_token_value
4040
when @current_token_value = scan(DATE)
4141
literal :DATE, @current_token_value
42+
when @current_token_value = scan(TIME)
43+
literal :TIME, @current_token_value
4244
when @current_token_value = scan(DECIMAL)
4345
literal :DECIMAL, @current_token_value
4446
when @current_token_value = scan(INTEGER)

0 commit comments

Comments
 (0)