Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
v1.3.6, 2026-06-23
* [BUGFIX] Parser crash when days()/weekdays() exceed max offset

v1.3.5, 2026-04-30
* [IMPROVEMENT] add date_date() function

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.5
1.3.6
40 changes: 32 additions & 8 deletions lib/sparkql/parser_tools.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,16 @@ def tokenize_literal_negation(number_token)
end

def tokenize_multiple(lit1, lit2)
if lit1.nil? || lit2.nil?
return nil if errors?

tokenizer_error(token: @lexer.last_field,
message: 'Invalid value in field list.',
status: :fatal,
syntax: true)
return nil
end

final_type = lit1[:type]
if lit1[:type] != lit2[:type]
final_type = coercible_types(lit1[:type], lit2[:type])
Expand Down Expand Up @@ -224,15 +234,17 @@ def tokenize_function(name, f_args)
resolver = function_resolver(name, args)
resolver.validate
if resolver.errors?
tokenizer_error(token: @lexer.last_field,
message: "Error parsing function #{resolver.errors.join(',')}",
status: :fatal,
syntax: true)
nil
else
result = resolver.call
result.nil? ? result : result.merge(condition: "#{name}(#{condition_list.join(',')})")
report_function_resolver_errors(resolver)
return nil
end

result = resolver.call
if result.nil?
report_function_resolver_errors(resolver) if resolver.errors?
return nil
end

result.merge(condition: "#{name}(#{condition_list.join(',')})")
end

def tokenize_arithmetic(lhs, operator, rhs)
Expand Down Expand Up @@ -448,4 +460,16 @@ def current_timestamp
def offset
@offset ||= current_timestamp.strftime('%:z')
end

private

def report_function_resolver_errors(resolver)
resolver.errors.each do |error|
tokenizer_error(token: error.token || @lexer.last_field,
message: error.message,
status: error.status,
syntax: error.syntax?,
constraint: error.constraint?)
end
end
end
12 changes: 12 additions & 0 deletions test/unit/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,18 @@ def test_cast_with_invalid_type
assert_equal 0, expressions.last[:block_group]
end

test 'oversized days() in Bt range returns parser error instead of raising' do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

[
'OriginalEntryTimestamp Bt days(0),days(365001)',
'OpenHouses Bt days(0),days(9223372036854775807)'
].each do |filter|
@parser = Parser.new
assert_nothing_raised { @parser.parse(filter) }
assert @parser.fatal_errors?, "Expected fatal error for #{filter}"
assert_match(/max offset/i, @parser.errors.first.message)
end
end

private

def parser_errors(filter)
Expand Down
Loading