Skip to content

Commit

Permalink
Merge pull request #1066 from Cali0707/sql-v1-fixes
Browse files Browse the repository at this point in the history
CESQL v1 fixes
  • Loading branch information
duglin authored Jul 15, 2024
2 parents 8efefb0 + 3ce6b2f commit dc3d9b1
Show file tree
Hide file tree
Showing 37 changed files with 505 additions and 221 deletions.
2 changes: 1 addition & 1 deletion sql/v2/CESQLLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ FALSE: 'FALSE';

DQUOTED_STRING_LITERAL: DQUOTA_STRING;
SQUOTED_STRING_LITERAL: SQUOTA_STRING;
INTEGER_LITERAL: INT_DIGIT+;
INTEGER_LITERAL: ('+' | '-')? INT_DIGIT+;

// Identifiers

Expand Down
152 changes: 152 additions & 0 deletions sql/v2/errors/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
Copyright 2024 The CloudEvents Authors
SPDX-License-Identifier: Apache-2.0
*/

package errors

import (
"fmt"
"strings"
)

type errorKind int

const (
parseError = iota
mathError
castError
missingAttributeError
missingFunctionError
functionEvaluationError
dummyLastError // always add new error classes ABOVE this error
)

type cesqlError struct {
kind errorKind
message string
}

func (eKind errorKind) String() string {
switch eKind {
case parseError:
return "parse error"
case mathError:
return "math error"
case castError:
return "cast error"
case missingAttributeError:
return "missing attribute error"
case missingFunctionError:
return "missing function error"
case functionEvaluationError:
return "function evaluation error"
default:
return "generic error"
}

}

func (cerr cesqlError) Error() string {
return fmt.Sprintf("%s: %s", cerr.kind, cerr.message)
}

func NewParseError(errs []error) error {
if len(errs) == 0 {
return nil
}

errorMessages := make([]string, 0, len(errs))
for _, err := range errs {
errorMessages = append(errorMessages, err.Error())
}

return cesqlError{
kind: parseError,
message: strings.Join(errorMessages, "|"),
}
}

func IsParseError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind == parseError
}
return false
}

func IsMathError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind == mathError
}
return false
}

func NewMathError(message string) error {
return cesqlError{
kind: mathError,
message: message,
}
}

func IsCastError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind == castError
}
return false
}

func NewCastError(err error) error {
return cesqlError{
kind: castError,
message: err.Error(),
}
}

func IsMissingAttributeError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind == missingAttributeError
}
return false
}

func NewMissingAttributeError(attribute string) error {
return cesqlError{
kind: missingAttributeError,
message: attribute,
}
}

func IsMissingFunctionError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind == missingFunctionError
}
return false
}

func NewMissingFunctionError(function string) error {
return cesqlError{
kind: missingFunctionError,
message: function,
}
}

func IsFunctionEvaluationError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind == functionEvaluationError
}
return false
}

func NewFunctionEvaluationError(err error) error {
return cesqlError{
kind: functionEvaluationError,
message: err.Error(),
}
}

func IsGenericError(err error) bool {
if cesqlErr, ok := err.(cesqlError); ok {
return cesqlErr.kind < 0 || cesqlErr.kind >= dummyLastError
}
return false
}
6 changes: 3 additions & 3 deletions sql/v2/expression/comparison_expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ type equalExpression struct {
func (s equalExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
leftVal, err := s.left.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

rightVal, err := s.right.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

leftVal, err = utils.Cast(leftVal, cesql.TypeFromVal(rightVal))
if err != nil {
return nil, err
return false, err
}

return (leftVal == rightVal) == s.equal, nil
Expand Down
24 changes: 19 additions & 5 deletions sql/v2/expression/function_invocation_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"

cesql "github.com/cloudevents/sdk-go/sql/v2"
sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors"
"github.com/cloudevents/sdk-go/sql/v2/runtime"
"github.com/cloudevents/sdk-go/sql/v2/utils"
cloudevents "github.com/cloudevents/sdk-go/v2"
Expand All @@ -22,31 +23,44 @@ type functionInvocationExpression struct {
func (expr functionInvocationExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
fn := runtime.ResolveFunction(expr.name, len(expr.argumentsExpression))
if fn == nil {
return nil, fmt.Errorf("cannot resolve function %s", expr.name)
return false, sqlerrors.NewMissingFunctionError(expr.name)
}

args := make([]interface{}, len(expr.argumentsExpression))

defaultVal := fn.ReturnType().ZeroValue()

for i, expr := range expr.argumentsExpression {
arg, err := expr.Evaluate(event)
if err != nil {
return nil, err
return defaultVal, err
}

argType := fn.ArgType(i)
if argType == nil {
return nil, fmt.Errorf("cannot resolve arg type at index %d", i)
return defaultVal, sqlerrors.NewFunctionEvaluationError(fmt.Errorf("cannot resolve arg type at index %d for function %s", i, fn.Name()))
}

arg, err = utils.Cast(arg, *argType)
if err != nil {
return nil, err
return defaultVal, err
}

args[i] = arg
}

return fn.Run(event, args)
result, err := fn.Run(event, args)
if result == nil {
if err != nil {
err = sqlerrors.NewFunctionEvaluationError(fmt.Errorf("function %s encountered error %w and did not return any value, defaulting to the default value for the function", fn.Name(), err))
} else {
err = sqlerrors.NewFunctionEvaluationError(fmt.Errorf("function %s did not return any value, defaulting to the default value for the function", fn.Name()))
}

return defaultVal, err
}

return result, err
}

func NewFunctionInvocationExpression(name string, argumentsExpression []cesql.Expression) cesql.Expression {
Expand Down
5 changes: 2 additions & 3 deletions sql/v2/expression/identifier_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
package expression

import (
"fmt"

cesql "github.com/cloudevents/sdk-go/sql/v2"
sqlerrors "github.com/cloudevents/sdk-go/sql/v2/errors"
"github.com/cloudevents/sdk-go/sql/v2/utils"
cloudevents "github.com/cloudevents/sdk-go/v2"
)
Expand All @@ -20,7 +19,7 @@ type identifierExpression struct {
func (l identifierExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
value := utils.GetAttribute(event, l.identifier)
if value == nil {
return nil, fmt.Errorf("missing attribute '%s'", l.identifier)
return false, sqlerrors.NewMissingAttributeError(l.identifier)
}

return value, nil
Expand Down
6 changes: 3 additions & 3 deletions sql/v2/expression/in_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ type inExpression struct {
func (l inExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
leftValue, err := l.leftExpression.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

for _, rightExpression := range l.setExpression {
rightValue, err := rightExpression.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

rightValue, err = utils.Cast(rightValue, cesql.TypeFromVal(leftValue))
if err != nil {
return nil, err
return false, err
}

if leftValue == rightValue {
Expand Down
8 changes: 4 additions & 4 deletions sql/v2/expression/integer_comparison_expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ type integerComparisonExpression struct {
func (s integerComparisonExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
leftVal, err := s.left.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

rightVal, err := s.right.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

leftVal, err = utils.Cast(leftVal, cesql.IntegerType)
if err != nil {
return nil, err
return false, err
}

rightVal, err = utils.Cast(rightVal, cesql.IntegerType)
if err != nil {
return nil, err
return false, err
}

return s.fn(leftVal.(int32), rightVal.(int32)), nil
Expand Down
4 changes: 2 additions & 2 deletions sql/v2/expression/like_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ type likeExpression struct {
func (l likeExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
val, err := l.child.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

val, err = utils.Cast(val, cesql.StringType)
if err != nil {
return nil, err
return false, err
}

return matchString(val.(string), l.pattern), nil
Expand Down
8 changes: 4 additions & 4 deletions sql/v2/expression/logic_expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ type logicExpression struct {
func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
leftVal, err := s.left.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

leftVal, err = utils.Cast(leftVal, cesql.BooleanType)
if err != nil {
return nil, err
return false, err
}

// Don't bother to check the other expression unless we need to
Expand All @@ -38,12 +38,12 @@ func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error)

rightVal, err := s.right.Evaluate(event)
if err != nil {
return nil, err
return false, err
}

rightVal, err = utils.Cast(rightVal, cesql.BooleanType)
if err != nil {
return nil, err
return false, err
}

return s.fn(leftVal.(bool), rightVal.(bool)), nil
Expand Down
Loading

0 comments on commit dc3d9b1

Please sign in to comment.