CESQL (#680)
* Bootstrapped CESQL parser Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Added tck Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * WIP, bootstrapped casting and types Implemented literal and negate expression Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Progress Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Most expressions implemented Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Implemented functions resolution Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Implemented Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * README + fix the tag-release.sh Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Copyright headers Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
parent
82f2b61ecd
commit
5198fc7683
|
|
@ -49,6 +49,7 @@ do
|
|||
"github.com/cloudevents/sdk-go/protocol/kafka_sarama/v2"
|
||||
"github.com/cloudevents/sdk-go/protocol/ws/v2"
|
||||
"github.com/cloudevents/sdk-go/observability/opencensus/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/v2" # NOTE: this needs to be last.
|
||||
)
|
||||
shift
|
||||
|
|
@ -111,6 +112,7 @@ MODULES=(
|
|||
"protocol/kafka_sarama"
|
||||
"protocol/ws"
|
||||
"observability/opencensus"
|
||||
"sql"
|
||||
)
|
||||
|
||||
for i in "${MODULES[@]}"; do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
lexer grammar CESQLLexer;
|
||||
|
||||
// NOTE:
|
||||
// This grammar is case-sensitive, although CESQL keywords are case-insensitive.
|
||||
// In order to implement case-insensitivity, check out
|
||||
// https://github.com/antlr/antlr4/blob/master/doc/case-insensitive-lexing.md#custom-character-streams-approach
|
||||
|
||||
// Skip tab, carriage return and newlines
|
||||
|
||||
SPACE: [ \t\r\n]+ -> skip;
|
||||
|
||||
// Fragments for Literal primitives
|
||||
|
||||
fragment ID_LITERAL: [a-zA-Z0-9]+;
|
||||
fragment DQUOTA_STRING: '"' ( '\\'. | '""' | ~('"'| '\\') )* '"';
|
||||
fragment SQUOTA_STRING: '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\'';
|
||||
fragment INT_DIGIT: [0-9];
|
||||
fragment FN_LITERAL: [A-Z] [A-Z_]*;
|
||||
|
||||
// Constructors symbols
|
||||
|
||||
LR_BRACKET: '(';
|
||||
RR_BRACKET: ')';
|
||||
COMMA: ',';
|
||||
SINGLE_QUOTE_SYMB: '\'';
|
||||
DOUBLE_QUOTE_SYMB: '"';
|
||||
|
||||
fragment QUOTE_SYMB
|
||||
: SINGLE_QUOTE_SYMB | DOUBLE_QUOTE_SYMB
|
||||
;
|
||||
|
||||
// Operators
|
||||
// - Logic
|
||||
|
||||
AND: 'AND';
|
||||
OR: 'OR';
|
||||
XOR: 'XOR';
|
||||
NOT: 'NOT';
|
||||
|
||||
// - Arithmetics
|
||||
|
||||
STAR: '*';
|
||||
DIVIDE: '/';
|
||||
MODULE: '%';
|
||||
PLUS: '+';
|
||||
MINUS: '-';
|
||||
|
||||
// - Comparison
|
||||
|
||||
EQUAL: '=';
|
||||
NOT_EQUAL: '!=';
|
||||
GREATER: '>';
|
||||
GREATER_OR_EQUAL: '>=';
|
||||
LESS: '<';
|
||||
LESS_GREATER: '<>';
|
||||
LESS_OR_EQUAL: '<=';
|
||||
|
||||
// Like, exists, in
|
||||
|
||||
LIKE: 'LIKE';
|
||||
EXISTS: 'EXISTS';
|
||||
IN: 'IN';
|
||||
|
||||
// Booleans
|
||||
|
||||
TRUE: 'TRUE';
|
||||
FALSE: 'FALSE';
|
||||
|
||||
// Literals
|
||||
|
||||
DQUOTED_STRING_LITERAL: DQUOTA_STRING;
|
||||
SQUOTED_STRING_LITERAL: SQUOTA_STRING;
|
||||
INTEGER_LITERAL: INT_DIGIT+;
|
||||
|
||||
// Identifiers
|
||||
|
||||
IDENTIFIER: [a-zA-Z]+;
|
||||
IDENTIFIER_WITH_NUMBER: [a-zA-Z0-9]+;
|
||||
FUNCTION_IDENTIFIER_WITH_UNDERSCORE: [A-Z] [A-Z_]*;
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
grammar CESQLParser;
|
||||
|
||||
import CESQLLexer;
|
||||
|
||||
// Entrypoint
|
||||
cesql: expression EOF;
|
||||
|
||||
// Structure of operations, function invocations and expression
|
||||
expression
|
||||
: functionIdentifier functionParameterList #functionInvocationExpression
|
||||
// unary operators are the highest priority
|
||||
| NOT expression #unaryLogicExpression
|
||||
| MINUS expression # unaryNumericExpression
|
||||
// LIKE, EXISTS and IN takes precedence over all the other binary operators
|
||||
| expression NOT? LIKE stringLiteral #likeExpression
|
||||
| EXISTS identifier #existsExpression
|
||||
| expression NOT? IN setExpression #inExpression
|
||||
// Numeric operations
|
||||
| expression (STAR | DIVIDE | MODULE) expression #binaryMultiplicativeExpression
|
||||
| expression (PLUS | MINUS) expression #binaryAdditiveExpression
|
||||
// Comparison operations
|
||||
| expression (EQUAL | NOT_EQUAL | LESS_GREATER | GREATER_OR_EQUAL | LESS_OR_EQUAL | LESS | GREATER) expression #binaryComparisonExpression
|
||||
// Logic operations
|
||||
|<assoc=right> expression (AND | OR | XOR) expression #binaryLogicExpression
|
||||
// Subexpressions and atoms
|
||||
| LR_BRACKET expression RR_BRACKET #subExpression
|
||||
| atom #atomExpression
|
||||
;
|
||||
|
||||
atom
|
||||
: booleanLiteral #booleanAtom
|
||||
| integerLiteral #integerAtom
|
||||
| stringLiteral #stringAtom
|
||||
| identifier #identifierAtom
|
||||
;
|
||||
|
||||
// Identifiers
|
||||
|
||||
identifier
|
||||
: (IDENTIFIER | IDENTIFIER_WITH_NUMBER)
|
||||
;
|
||||
functionIdentifier
|
||||
: (IDENTIFIER | FUNCTION_IDENTIFIER_WITH_UNDERSCORE)
|
||||
;
|
||||
|
||||
// Literals
|
||||
|
||||
booleanLiteral: (TRUE | FALSE);
|
||||
stringLiteral: (DQUOTED_STRING_LITERAL | SQUOTED_STRING_LITERAL);
|
||||
integerLiteral: INTEGER_LITERAL;
|
||||
|
||||
// Functions
|
||||
|
||||
functionParameterList
|
||||
: LR_BRACKET ( expression ( COMMA expression )* )? RR_BRACKET
|
||||
;
|
||||
|
||||
// Sets
|
||||
|
||||
setExpression
|
||||
: LR_BRACKET expression ( COMMA expression )* RR_BRACKET // Empty sets are not allowed
|
||||
;
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# CloudEvents Expression Language Go implementation
|
||||
|
||||
CloudEvents Expression Language implementation.
|
||||
|
||||
Note: this package is a work in progress, APIs might break in future releases.
|
||||
|
||||
## User guide
|
||||
|
||||
To start using it:
|
||||
|
||||
```go
|
||||
import cesqlparser "github.com/cloudevents/sdk-go/sql/v2/parser"
|
||||
|
||||
// Parse the expression
|
||||
expression, err := cesqlparser.Parse("subject = 'Hello world'")
|
||||
|
||||
// Res can be either int32, bool or string
|
||||
res, err := expression.Evaluate(event)
|
||||
```
|
||||
|
||||
## Development guide
|
||||
|
||||
To regenerate the parser, make sure you have [ANTLR4 installed](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md) and then run:
|
||||
|
||||
```shell
|
||||
antlr4 -Dlanguage=Go -package gen -o gen -visitor -no-listener CESQLParser.g4
|
||||
```
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package v2
|
||||
|
||||
import cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
|
||||
// Expression represents a parsed CloudEvents SQL Expression.
|
||||
type Expression interface {
|
||||
|
||||
// Evaluate the expression using the provided input type.
|
||||
// The return value can be either int32, bool or string.
|
||||
// The evaluation fails as soon as an error arises.
|
||||
Evaluate(event cloudevents.Event) (interface{}, error)
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
|
||||
type baseUnaryExpression struct {
|
||||
child cesql.Expression
|
||||
}
|
||||
|
||||
type baseBinaryExpression struct {
|
||||
left cesql.Expression
|
||||
right cesql.Expression
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type equalExpression struct {
|
||||
baseBinaryExpression
|
||||
equal bool
|
||||
}
|
||||
|
||||
func (s equalExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
leftVal, err := s.left.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err := s.right.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leftVal, err = utils.Cast(leftVal, cesql.TypeFromVal(rightVal))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return (leftVal == rightVal) == s.equal, nil
|
||||
}
|
||||
|
||||
func NewEqualExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return equalExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
equal: true,
|
||||
}
|
||||
}
|
||||
|
||||
func NewNotEqualExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return equalExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
equal: false,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type existsExpression struct {
|
||||
identifier string
|
||||
}
|
||||
|
||||
func (l existsExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
return utils.ContainsAttribute(event, l.identifier), nil
|
||||
}
|
||||
|
||||
func NewExistsExpression(identifier string) cesql.Expression {
|
||||
return existsExpression{identifier: identifier}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/runtime"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type functionInvocationExpression struct {
|
||||
name string
|
||||
argumentsExpression []cesql.Expression
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
args := make([]interface{}, len(expr.argumentsExpression))
|
||||
|
||||
for i, expr := range expr.argumentsExpression {
|
||||
arg, err := expr.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
argType := fn.ArgType(i)
|
||||
if argType == nil {
|
||||
return nil, fmt.Errorf("cannot resolve arg type at index %d", i)
|
||||
}
|
||||
|
||||
arg, err = utils.Cast(arg, *argType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args[i] = arg
|
||||
}
|
||||
|
||||
return fn.Run(event, args)
|
||||
}
|
||||
|
||||
func NewFunctionInvocationExpression(name string, argumentsExpression []cesql.Expression) cesql.Expression {
|
||||
return functionInvocationExpression{
|
||||
name: name,
|
||||
argumentsExpression: argumentsExpression,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type identifierExpression struct {
|
||||
identifier string
|
||||
}
|
||||
|
||||
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 value, nil
|
||||
}
|
||||
|
||||
func NewIdentifierExpression(identifier string) cesql.Expression {
|
||||
return identifierExpression{identifier: identifier}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type inExpression struct {
|
||||
leftExpression cesql.Expression
|
||||
setExpression []cesql.Expression
|
||||
}
|
||||
|
||||
func (l inExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
leftValue, err := l.leftExpression.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, rightExpression := range l.setExpression {
|
||||
rightValue, err := rightExpression.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightValue, err = utils.Cast(rightValue, cesql.TypeFromVal(leftValue))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if leftValue == rightValue {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func NewInExpression(leftExpression cesql.Expression, setExpression []cesql.Expression) cesql.Expression {
|
||||
return inExpression{leftExpression, setExpression}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type integerComparisonExpression struct {
|
||||
baseBinaryExpression
|
||||
fn func(x, y int32) bool
|
||||
}
|
||||
|
||||
func (s integerComparisonExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
leftVal, err := s.left.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err := s.right.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leftVal, err = utils.Cast(leftVal, cesql.IntegerType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err = utils.Cast(rightVal, cesql.IntegerType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.fn(leftVal.(int32), rightVal.(int32)), nil
|
||||
}
|
||||
|
||||
func NewLessExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return integerComparisonExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) bool {
|
||||
return x < y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewLessOrEqualExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return integerComparisonExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) bool {
|
||||
return x <= y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewGreaterExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return integerComparisonExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) bool {
|
||||
return x > y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewGreaterOrEqualExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return integerComparisonExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) bool {
|
||||
return x >= y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type likeExpression struct {
|
||||
baseUnaryExpression
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func (l likeExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
val, err := l.child.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val, err = utils.Cast(val, cesql.StringType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return l.pattern.MatchString(val.(string)), nil
|
||||
}
|
||||
|
||||
func NewLikeExpression(child cesql.Expression, pattern string) (cesql.Expression, error) {
|
||||
// Converting to regex is not the most performant impl, but it works
|
||||
p, err := convertLikePatternToRegex(pattern)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return likeExpression{
|
||||
baseUnaryExpression: baseUnaryExpression{
|
||||
child: child,
|
||||
},
|
||||
pattern: p,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func convertLikePatternToRegex(pattern string) (*regexp.Regexp, error) {
|
||||
var chunks []string
|
||||
chunks = append(chunks, "^")
|
||||
|
||||
var chunk strings.Builder
|
||||
|
||||
for i := 0; i < len(pattern); i++ {
|
||||
if pattern[i] == '\\' && i < len(pattern)-1 {
|
||||
if pattern[i+1] == '%' {
|
||||
// \% case
|
||||
chunk.WriteRune('%')
|
||||
chunks = append(chunks, "\\Q"+chunk.String()+"\\E")
|
||||
chunk.Reset()
|
||||
i++
|
||||
continue
|
||||
} else if pattern[i+1] == '_' {
|
||||
// \_ case
|
||||
chunk.WriteRune('_')
|
||||
chunks = append(chunks, "\\Q"+chunk.String()+"\\E")
|
||||
chunk.Reset()
|
||||
i++
|
||||
continue
|
||||
}
|
||||
} else if pattern[i] == '_' {
|
||||
// replace with .
|
||||
chunks = append(chunks, "\\Q"+chunk.String()+"\\E")
|
||||
chunk.Reset()
|
||||
chunks = append(chunks, ".")
|
||||
} else if pattern[i] == '%' {
|
||||
// replace with .*
|
||||
chunks = append(chunks, "\\Q"+chunk.String()+"\\E")
|
||||
chunk.Reset()
|
||||
chunks = append(chunks, ".*")
|
||||
} else {
|
||||
chunk.WriteByte(pattern[i])
|
||||
}
|
||||
}
|
||||
|
||||
if chunk.Len() != 0 {
|
||||
chunks = append(chunks, "\\Q"+chunk.String()+"\\E")
|
||||
}
|
||||
|
||||
chunks = append(chunks, "$")
|
||||
|
||||
return regexp.Compile(strings.Join(chunks, ""))
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type literalExpression struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (l literalExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
return l.value, nil
|
||||
}
|
||||
|
||||
func NewLiteralExpression(value interface{}) cesql.Expression {
|
||||
return literalExpression{value: value}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type logicExpression struct {
|
||||
baseBinaryExpression
|
||||
fn func(x, y bool) bool
|
||||
}
|
||||
|
||||
func (s logicExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
leftVal, err := s.left.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err := s.right.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leftVal, err = utils.Cast(leftVal, cesql.BooleanType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err = utils.Cast(rightVal, cesql.BooleanType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.fn(leftVal.(bool), rightVal.(bool)), nil
|
||||
}
|
||||
|
||||
func NewAndExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return logicExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y bool) bool {
|
||||
return x && y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewOrExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return logicExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y bool) bool {
|
||||
return x || y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewXorExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return logicExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y bool) bool {
|
||||
return x != y
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type mathExpression struct {
|
||||
baseBinaryExpression
|
||||
fn func(x, y int32) (int32, error)
|
||||
}
|
||||
|
||||
func (s mathExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
leftVal, err := s.left.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err := s.right.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leftVal, err = utils.Cast(leftVal, cesql.IntegerType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rightVal, err = utils.Cast(rightVal, cesql.IntegerType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.fn(leftVal.(int32), rightVal.(int32))
|
||||
}
|
||||
|
||||
func NewSumExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return mathExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) (int32, error) {
|
||||
return x + y, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDifferenceExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return mathExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) (int32, error) {
|
||||
return x - y, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewMultiplicationExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return mathExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) (int32, error) {
|
||||
return x * y, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewModuleExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return mathExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) (int32, error) {
|
||||
if y == 0 {
|
||||
return 0, errors.New("math error: division by zero")
|
||||
}
|
||||
return x % y, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewDivisionExpression(left cesql.Expression, right cesql.Expression) cesql.Expression {
|
||||
return mathExpression{
|
||||
baseBinaryExpression: baseBinaryExpression{
|
||||
left: left,
|
||||
right: right,
|
||||
},
|
||||
fn: func(x, y int32) (int32, error) {
|
||||
if y == 0 {
|
||||
return 0, errors.New("math error: division by zero")
|
||||
}
|
||||
return x / y, nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type negateExpression baseUnaryExpression
|
||||
|
||||
func (l negateExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
val, err := l.child.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val, err = utils.Cast(val, cesql.IntegerType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return -(val.(int32)), nil
|
||||
}
|
||||
|
||||
func NewNegateExpression(child cesql.Expression) cesql.Expression {
|
||||
return negateExpression{child: child}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package expression
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type notExpression baseUnaryExpression
|
||||
|
||||
func (l notExpression) Evaluate(event cloudevents.Event) (interface{}, error) {
|
||||
val, err := l.child.Evaluate(event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
val, err = utils.Cast(val, cesql.BooleanType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return !(val.(bool)), nil
|
||||
}
|
||||
|
||||
func NewNotExpression(child cesql.Expression) cesql.Expression {
|
||||
return notExpression{child: child}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package v2
|
||||
|
||||
import cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
|
||||
type Function interface {
|
||||
Name() string
|
||||
Arity() int
|
||||
IsVariadic() bool
|
||||
ArgType(index int) *Type
|
||||
|
||||
Run(event cloudevents.Event, arguments []interface{}) (interface{}, error)
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package function
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/utils"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
var IntFunction function = function{
|
||||
name: "INT",
|
||||
fixedArgs: []cesql.Type{cesql.AnyType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return utils.Cast(i[0], cesql.IntegerType)
|
||||
},
|
||||
}
|
||||
|
||||
var BoolFunction function = function{
|
||||
name: "BOOL",
|
||||
fixedArgs: []cesql.Type{cesql.AnyType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return utils.Cast(i[0], cesql.BooleanType)
|
||||
},
|
||||
}
|
||||
|
||||
var StringFunction function = function{
|
||||
name: "STRING",
|
||||
fixedArgs: []cesql.Type{cesql.AnyType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return utils.Cast(i[0], cesql.StringType)
|
||||
},
|
||||
}
|
||||
|
||||
var IsIntFunction function = function{
|
||||
name: "IS_INT",
|
||||
fixedArgs: []cesql.Type{cesql.AnyType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return utils.CanCast(i[0], cesql.IntegerType), nil
|
||||
},
|
||||
}
|
||||
|
||||
var IsBoolFunction function = function{
|
||||
name: "IS_BOOL",
|
||||
fixedArgs: []cesql.Type{cesql.AnyType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return utils.CanCast(i[0], cesql.BooleanType), nil
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package function
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type function struct {
|
||||
name string
|
||||
fixedArgs []cesql.Type
|
||||
variadicArgs *cesql.Type
|
||||
fn func(cloudevents.Event, []interface{}) (interface{}, error)
|
||||
}
|
||||
|
||||
func (f function) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f function) Arity() int {
|
||||
return len(f.fixedArgs)
|
||||
}
|
||||
|
||||
func (f function) IsVariadic() bool {
|
||||
return f.variadicArgs != nil
|
||||
}
|
||||
|
||||
func (f function) ArgType(index int) *cesql.Type {
|
||||
if index < len(f.fixedArgs) {
|
||||
return &f.fixedArgs[index]
|
||||
}
|
||||
return f.variadicArgs
|
||||
}
|
||||
|
||||
func (f function) Run(event cloudevents.Event, arguments []interface{}) (interface{}, error) {
|
||||
return f.fn(event, arguments)
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package function
|
||||
|
||||
import (
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
var AbsFunction function = function{
|
||||
name: "ABS",
|
||||
fixedArgs: []cesql.Type{cesql.IntegerType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
x := i[0].(int32)
|
||||
if x < 0 {
|
||||
return -x, nil
|
||||
}
|
||||
return x, nil
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package function
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
var LengthFunction function = function{
|
||||
name: "LENGTH",
|
||||
fixedArgs: []cesql.Type{cesql.StringType},
|
||||
variadicArgs: nil,
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return int32(len(i[0].(string))), nil
|
||||
},
|
||||
}
|
||||
|
||||
var ConcatFunction function = function{
|
||||
name: "CONCAT",
|
||||
variadicArgs: cesql.TypePtr(cesql.StringType),
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
var sb strings.Builder
|
||||
for _, v := range i {
|
||||
sb.WriteString(v.(string))
|
||||
}
|
||||
return sb.String(), nil
|
||||
},
|
||||
}
|
||||
|
||||
var ConcatWSFunction function = function{
|
||||
name: "CONCAT_WS",
|
||||
fixedArgs: []cesql.Type{cesql.StringType},
|
||||
variadicArgs: cesql.TypePtr(cesql.StringType),
|
||||
fn: func(event cloudevents.Event, args []interface{}) (interface{}, error) {
|
||||
if len(args) == 1 {
|
||||
return "", nil
|
||||
}
|
||||
separator := args[0].(string)
|
||||
|
||||
var sb strings.Builder
|
||||
for i := 1; i < len(args)-1; i++ {
|
||||
sb.WriteString(args[i].(string))
|
||||
sb.WriteString(separator)
|
||||
}
|
||||
sb.WriteString(args[len(args)-1].(string))
|
||||
return sb.String(), nil
|
||||
},
|
||||
}
|
||||
|
||||
var LowerFunction function = function{
|
||||
name: "LOWER",
|
||||
fixedArgs: []cesql.Type{cesql.StringType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return strings.ToLower(i[0].(string)), nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpperFunction function = function{
|
||||
name: "UPPER",
|
||||
fixedArgs: []cesql.Type{cesql.StringType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return strings.ToUpper(i[0].(string)), nil
|
||||
},
|
||||
}
|
||||
|
||||
var TrimFunction function = function{
|
||||
name: "TRIM",
|
||||
fixedArgs: []cesql.Type{cesql.StringType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
return strings.TrimSpace(i[0].(string)), nil
|
||||
},
|
||||
}
|
||||
|
||||
var LeftFunction function = function{
|
||||
name: "LEFT",
|
||||
fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
str := i[0].(string)
|
||||
y := int(i[1].(int32))
|
||||
|
||||
if y > len(str) {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
if y < 0 {
|
||||
return nil, fmt.Errorf("LEFT y argument is < 0: %d", y)
|
||||
}
|
||||
|
||||
return str[0:y], nil
|
||||
},
|
||||
}
|
||||
|
||||
var RightFunction function = function{
|
||||
name: "RIGHT",
|
||||
fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
str := i[0].(string)
|
||||
y := int(i[1].(int32))
|
||||
|
||||
if y > len(str) {
|
||||
return str, nil
|
||||
}
|
||||
|
||||
if y < 0 {
|
||||
return nil, fmt.Errorf("RIGHT y argument is < 0: %d", y)
|
||||
}
|
||||
|
||||
return str[len(str)-y:], nil
|
||||
},
|
||||
}
|
||||
|
||||
var SubstringFunction function = function{
|
||||
name: "SUBSTRING",
|
||||
fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
str := i[0].(string)
|
||||
pos := int(i[1].(int32))
|
||||
|
||||
if pos == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if pos < -len(str) || pos > len(str) {
|
||||
return "", fmt.Errorf("SUBSTRING invalid pos argument: %d", pos)
|
||||
}
|
||||
|
||||
var beginning int
|
||||
if pos < 0 {
|
||||
beginning = len(str) + pos
|
||||
} else {
|
||||
beginning = pos - 1
|
||||
}
|
||||
|
||||
return str[beginning:], nil
|
||||
},
|
||||
}
|
||||
|
||||
var SubstringWithLengthFunction function = function{
|
||||
name: "SUBSTRING",
|
||||
fixedArgs: []cesql.Type{cesql.StringType, cesql.IntegerType, cesql.IntegerType},
|
||||
fn: func(event cloudevents.Event, i []interface{}) (interface{}, error) {
|
||||
str := i[0].(string)
|
||||
pos := int(i[1].(int32))
|
||||
length := int(i[2].(int32))
|
||||
|
||||
if pos == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if pos < -len(str) || pos > len(str) {
|
||||
return "", fmt.Errorf("SUBSTRING invalid pos argument: %d", pos)
|
||||
}
|
||||
|
||||
var beginning int
|
||||
if pos < 0 {
|
||||
beginning = len(str) + pos
|
||||
} else {
|
||||
beginning = pos - 1
|
||||
}
|
||||
|
||||
var end int
|
||||
if beginning+length > len(str) {
|
||||
end = len(str)
|
||||
} else {
|
||||
end = beginning + length
|
||||
}
|
||||
|
||||
return str[beginning:end], nil
|
||||
},
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
token literal names:
|
||||
null
|
||||
null
|
||||
'('
|
||||
')'
|
||||
','
|
||||
'\''
|
||||
'"'
|
||||
'AND'
|
||||
'OR'
|
||||
'XOR'
|
||||
'NOT'
|
||||
'*'
|
||||
'/'
|
||||
'%'
|
||||
'+'
|
||||
'-'
|
||||
'='
|
||||
'!='
|
||||
'>'
|
||||
'>='
|
||||
'<'
|
||||
'<>'
|
||||
'<='
|
||||
'LIKE'
|
||||
'EXISTS'
|
||||
'IN'
|
||||
'TRUE'
|
||||
'FALSE'
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
null
|
||||
|
||||
token symbolic names:
|
||||
null
|
||||
SPACE
|
||||
LR_BRACKET
|
||||
RR_BRACKET
|
||||
COMMA
|
||||
SINGLE_QUOTE_SYMB
|
||||
DOUBLE_QUOTE_SYMB
|
||||
AND
|
||||
OR
|
||||
XOR
|
||||
NOT
|
||||
STAR
|
||||
DIVIDE
|
||||
MODULE
|
||||
PLUS
|
||||
MINUS
|
||||
EQUAL
|
||||
NOT_EQUAL
|
||||
GREATER
|
||||
GREATER_OR_EQUAL
|
||||
LESS
|
||||
LESS_GREATER
|
||||
LESS_OR_EQUAL
|
||||
LIKE
|
||||
EXISTS
|
||||
IN
|
||||
TRUE
|
||||
FALSE
|
||||
DQUOTED_STRING_LITERAL
|
||||
SQUOTED_STRING_LITERAL
|
||||
INTEGER_LITERAL
|
||||
IDENTIFIER
|
||||
IDENTIFIER_WITH_NUMBER
|
||||
FUNCTION_IDENTIFIER_WITH_UNDERSCORE
|
||||
|
||||
rule names:
|
||||
cesql
|
||||
expression
|
||||
atom
|
||||
identifier
|
||||
functionIdentifier
|
||||
booleanLiteral
|
||||
stringLiteral
|
||||
integerLiteral
|
||||
functionParameterList
|
||||
setExpression
|
||||
|
||||
|
||||
atn:
|
||||
[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 35, 112, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 41, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 57, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 63, 10, 3, 3, 3, 3, 3, 7, 3, 67, 10, 3, 12, 3, 14, 3, 70, 11, 3, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 76, 10, 4, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 7, 10, 92, 10, 10, 12, 10, 14, 10, 95, 11, 10, 5, 10, 97, 10, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 7, 11, 105, 10, 11, 12, 11, 14, 11, 108, 11, 11, 3, 11, 3, 11, 3, 11, 2, 3, 4, 12, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 2, 10, 3, 2, 13, 15, 3, 2, 16, 17, 3, 2, 18, 24, 3, 2, 9, 11, 3, 2, 33, 34, 4, 2, 33, 33, 35, 35, 3, 2, 28, 29, 3, 2, 30, 31, 2, 120, 2, 22, 3, 2, 2, 2, 4, 40, 3, 2, 2, 2, 6, 75, 3, 2, 2, 2, 8, 77, 3, 2, 2, 2, 10, 79, 3, 2, 2, 2, 12, 81, 3, 2, 2, 2, 14, 83, 3, 2, 2, 2, 16, 85, 3, 2, 2, 2, 18, 87, 3, 2, 2, 2, 20, 100, 3, 2, 2, 2, 22, 23, 5, 4, 3, 2, 23, 24, 7, 2, 2, 3, 24, 3, 3, 2, 2, 2, 25, 26, 8, 3, 1, 2, 26, 27, 5, 10, 6, 2, 27, 28, 5, 18, 10, 2, 28, 41, 3, 2, 2, 2, 29, 30, 7, 12, 2, 2, 30, 41, 5, 4, 3, 13, 31, 32, 7, 17, 2, 2, 32, 41, 5, 4, 3, 12, 33, 34, 7, 26, 2, 2, 34, 41, 5, 8, 5, 2, 35, 36, 7, 4, 2, 2, 36, 37, 5, 4, 3, 2, 37, 38, 7, 5, 2, 2, 38, 41, 3, 2, 2, 2, 39, 41, 5, 6, 4, 2, 40, 25, 3, 2, 2, 2, 40, 29, 3, 2, 2, 2, 40, 31, 3, 2, 2, 2, 40, 33, 3, 2, 2, 2, 40, 35, 3, 2, 2, 2, 40, 39, 3, 2, 2, 2, 41, 68, 3, 2, 2, 2, 42, 43, 12, 8, 2, 2, 43, 44, 9, 2, 2, 2, 44, 67, 5, 4, 3, 9, 45, 46, 12, 7, 2, 2, 46, 47, 9, 3, 2, 2, 47, 67, 5, 4, 3, 8, 48, 49, 12, 6, 2, 2, 49, 50, 9, 4, 2, 2, 50, 67, 5, 4, 3, 7, 51, 52, 12, 5, 2, 2, 52, 53, 9, 5, 2, 2, 53, 67, 5, 4, 3, 5, 54, 56, 12, 11, 2, 2, 55, 57, 7, 12, 2, 2, 56, 55, 3, 2, 2, 2, 56, 57, 3, 2, 2, 2, 57, 58, 3, 2, 2, 2, 58, 59, 7, 25, 2, 2, 59, 67, 5, 14, 8, 2, 60, 62, 12, 9, 2, 2, 61, 63, 7, 12, 2, 2, 62, 61, 3, 2, 2, 2, 62, 63, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 65, 7, 27, 2, 2, 65, 67, 5, 20, 11, 2, 66, 42, 3, 2, 2, 2, 66, 45, 3, 2, 2, 2, 66, 48, 3, 2, 2, 2, 66, 51, 3, 2, 2, 2, 66, 54, 3, 2, 2, 2, 66, 60, 3, 2, 2, 2, 67, 70, 3, 2, 2, 2, 68, 66, 3, 2, 2, 2, 68, 69, 3, 2, 2, 2, 69, 5, 3, 2, 2, 2, 70, 68, 3, 2, 2, 2, 71, 76, 5, 12, 7, 2, 72, 76, 5, 16, 9, 2, 73, 76, 5, 14, 8, 2, 74, 76, 5, 8, 5, 2, 75, 71, 3, 2, 2, 2, 75, 72, 3, 2, 2, 2, 75, 73, 3, 2, 2, 2, 75, 74, 3, 2, 2, 2, 76, 7, 3, 2, 2, 2, 77, 78, 9, 6, 2, 2, 78, 9, 3, 2, 2, 2, 79, 80, 9, 7, 2, 2, 80, 11, 3, 2, 2, 2, 81, 82, 9, 8, 2, 2, 82, 13, 3, 2, 2, 2, 83, 84, 9, 9, 2, 2, 84, 15, 3, 2, 2, 2, 85, 86, 7, 32, 2, 2, 86, 17, 3, 2, 2, 2, 87, 96, 7, 4, 2, 2, 88, 93, 5, 4, 3, 2, 89, 90, 7, 6, 2, 2, 90, 92, 5, 4, 3, 2, 91, 89, 3, 2, 2, 2, 92, 95, 3, 2, 2, 2, 93, 91, 3, 2, 2, 2, 93, 94, 3, 2, 2, 2, 94, 97, 3, 2, 2, 2, 95, 93, 3, 2, 2, 2, 96, 88, 3, 2, 2, 2, 96, 97, 3, 2, 2, 2, 97, 98, 3, 2, 2, 2, 98, 99, 7, 5, 2, 2, 99, 19, 3, 2, 2, 2, 100, 101, 7, 4, 2, 2, 101, 106, 5, 4, 3, 2, 102, 103, 7, 6, 2, 2, 103, 105, 5, 4, 3, 2, 104, 102, 3, 2, 2, 2, 105, 108, 3, 2, 2, 2, 106, 104, 3, 2, 2, 2, 106, 107, 3, 2, 2, 2, 107, 109, 3, 2, 2, 2, 108, 106, 3, 2, 2, 2, 109, 110, 7, 5, 2, 2, 110, 21, 3, 2, 2, 2, 11, 40, 56, 62, 66, 68, 75, 93, 96, 106]
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
SPACE=1
|
||||
LR_BRACKET=2
|
||||
RR_BRACKET=3
|
||||
COMMA=4
|
||||
SINGLE_QUOTE_SYMB=5
|
||||
DOUBLE_QUOTE_SYMB=6
|
||||
AND=7
|
||||
OR=8
|
||||
XOR=9
|
||||
NOT=10
|
||||
STAR=11
|
||||
DIVIDE=12
|
||||
MODULE=13
|
||||
PLUS=14
|
||||
MINUS=15
|
||||
EQUAL=16
|
||||
NOT_EQUAL=17
|
||||
GREATER=18
|
||||
GREATER_OR_EQUAL=19
|
||||
LESS=20
|
||||
LESS_GREATER=21
|
||||
LESS_OR_EQUAL=22
|
||||
LIKE=23
|
||||
EXISTS=24
|
||||
IN=25
|
||||
TRUE=26
|
||||
FALSE=27
|
||||
DQUOTED_STRING_LITERAL=28
|
||||
SQUOTED_STRING_LITERAL=29
|
||||
INTEGER_LITERAL=30
|
||||
IDENTIFIER=31
|
||||
IDENTIFIER_WITH_NUMBER=32
|
||||
FUNCTION_IDENTIFIER_WITH_UNDERSCORE=33
|
||||
'('=2
|
||||
')'=3
|
||||
','=4
|
||||
'\''=5
|
||||
'"'=6
|
||||
'AND'=7
|
||||
'OR'=8
|
||||
'XOR'=9
|
||||
'NOT'=10
|
||||
'*'=11
|
||||
'/'=12
|
||||
'%'=13
|
||||
'+'=14
|
||||
'-'=15
|
||||
'='=16
|
||||
'!='=17
|
||||
'>'=18
|
||||
'>='=19
|
||||
'<'=20
|
||||
'<>'=21
|
||||
'<='=22
|
||||
'LIKE'=23
|
||||
'EXISTS'=24
|
||||
'IN'=25
|
||||
'TRUE'=26
|
||||
'FALSE'=27
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,59 @@
|
|||
SPACE=1
|
||||
LR_BRACKET=2
|
||||
RR_BRACKET=3
|
||||
COMMA=4
|
||||
SINGLE_QUOTE_SYMB=5
|
||||
DOUBLE_QUOTE_SYMB=6
|
||||
AND=7
|
||||
OR=8
|
||||
XOR=9
|
||||
NOT=10
|
||||
STAR=11
|
||||
DIVIDE=12
|
||||
MODULE=13
|
||||
PLUS=14
|
||||
MINUS=15
|
||||
EQUAL=16
|
||||
NOT_EQUAL=17
|
||||
GREATER=18
|
||||
GREATER_OR_EQUAL=19
|
||||
LESS=20
|
||||
LESS_GREATER=21
|
||||
LESS_OR_EQUAL=22
|
||||
LIKE=23
|
||||
EXISTS=24
|
||||
IN=25
|
||||
TRUE=26
|
||||
FALSE=27
|
||||
DQUOTED_STRING_LITERAL=28
|
||||
SQUOTED_STRING_LITERAL=29
|
||||
INTEGER_LITERAL=30
|
||||
IDENTIFIER=31
|
||||
IDENTIFIER_WITH_NUMBER=32
|
||||
FUNCTION_IDENTIFIER_WITH_UNDERSCORE=33
|
||||
'('=2
|
||||
')'=3
|
||||
','=4
|
||||
'\''=5
|
||||
'"'=6
|
||||
'AND'=7
|
||||
'OR'=8
|
||||
'XOR'=9
|
||||
'NOT'=10
|
||||
'*'=11
|
||||
'/'=12
|
||||
'%'=13
|
||||
'+'=14
|
||||
'-'=15
|
||||
'='=16
|
||||
'!='=17
|
||||
'>'=18
|
||||
'>='=19
|
||||
'<'=20
|
||||
'<>'=21
|
||||
'<='=22
|
||||
'LIKE'=23
|
||||
'EXISTS'=24
|
||||
'IN'=25
|
||||
'TRUE'=26
|
||||
'FALSE'=27
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Code generated from CESQLParser.g4 by ANTLR 4.9. DO NOT EDIT.
|
||||
|
||||
package gen // CESQLParser
|
||||
import "github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
|
||||
type BaseCESQLParserVisitor struct {
|
||||
*antlr.BaseParseTreeVisitor
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitCesql(ctx *CesqlContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitInExpression(ctx *InExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitBinaryComparisonExpression(ctx *BinaryComparisonExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitAtomExpression(ctx *AtomExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitExistsExpression(ctx *ExistsExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitBinaryLogicExpression(ctx *BinaryLogicExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitLikeExpression(ctx *LikeExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitFunctionInvocationExpression(ctx *FunctionInvocationExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitBinaryMultiplicativeExpression(ctx *BinaryMultiplicativeExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitUnaryLogicExpression(ctx *UnaryLogicExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitUnaryNumericExpression(ctx *UnaryNumericExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitSubExpression(ctx *SubExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitBinaryAdditiveExpression(ctx *BinaryAdditiveExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitBooleanAtom(ctx *BooleanAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitIntegerAtom(ctx *IntegerAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitStringAtom(ctx *StringAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitIdentifierAtom(ctx *IdentifierAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitIdentifier(ctx *IdentifierContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitBooleanLiteral(ctx *BooleanLiteralContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitStringLiteral(ctx *StringLiteralContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitIntegerLiteral(ctx *IntegerLiteralContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitFunctionParameterList(ctx *FunctionParameterListContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseCESQLParserVisitor) VisitSetExpression(ctx *SetExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Code generated from CESQLParser.g4 by ANTLR 4.9. DO NOT EDIT.
|
||||
|
||||
package gen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode"
|
||||
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
)
|
||||
|
||||
// Suppress unused import error
|
||||
var _ = fmt.Printf
|
||||
var _ = unicode.IsLetter
|
||||
|
||||
var serializedLexerAtn = []uint16{
|
||||
3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 35, 237,
|
||||
8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7,
|
||||
9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12,
|
||||
4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4,
|
||||
18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23,
|
||||
9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9,
|
||||
28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33,
|
||||
4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4,
|
||||
39, 9, 39, 4, 40, 9, 40, 3, 2, 6, 2, 83, 10, 2, 13, 2, 14, 2, 84, 3, 2,
|
||||
3, 2, 3, 3, 6, 3, 90, 10, 3, 13, 3, 14, 3, 91, 3, 4, 3, 4, 3, 4, 3, 4,
|
||||
3, 4, 3, 4, 7, 4, 100, 10, 4, 12, 4, 14, 4, 103, 11, 4, 3, 4, 3, 4, 3,
|
||||
5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 7, 5, 113, 10, 5, 12, 5, 14, 5, 116, 11,
|
||||
5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 7, 3, 7, 7, 7, 124, 10, 7, 12, 7, 14, 7,
|
||||
127, 11, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 12,
|
||||
3, 12, 3, 13, 3, 13, 5, 13, 141, 10, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3,
|
||||
15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17,
|
||||
3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22, 3, 22, 3,
|
||||
23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 27,
|
||||
3, 27, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3,
|
||||
30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32,
|
||||
3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3,
|
||||
34, 3, 34, 3, 35, 3, 35, 3, 36, 3, 36, 3, 37, 6, 37, 217, 10, 37, 13, 37,
|
||||
14, 37, 218, 3, 38, 6, 38, 222, 10, 38, 13, 38, 14, 38, 223, 3, 39, 6,
|
||||
39, 227, 10, 39, 13, 39, 14, 39, 228, 3, 40, 3, 40, 7, 40, 233, 10, 40,
|
||||
12, 40, 14, 40, 236, 11, 40, 2, 2, 41, 3, 3, 5, 2, 7, 2, 9, 2, 11, 2, 13,
|
||||
2, 15, 4, 17, 5, 19, 6, 21, 7, 23, 8, 25, 2, 27, 9, 29, 10, 31, 11, 33,
|
||||
12, 35, 13, 37, 14, 39, 15, 41, 16, 43, 17, 45, 18, 47, 19, 49, 20, 51,
|
||||
21, 53, 22, 55, 23, 57, 24, 59, 25, 61, 26, 63, 27, 65, 28, 67, 29, 69,
|
||||
30, 71, 31, 73, 32, 75, 33, 77, 34, 79, 35, 3, 2, 10, 5, 2, 11, 12, 15,
|
||||
15, 34, 34, 5, 2, 50, 59, 67, 92, 99, 124, 4, 2, 36, 36, 94, 94, 4, 2,
|
||||
41, 41, 94, 94, 3, 2, 50, 59, 3, 2, 67, 92, 4, 2, 67, 92, 97, 97, 4, 2,
|
||||
67, 92, 99, 124, 2, 244, 2, 3, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3,
|
||||
2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 27,
|
||||
3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2,
|
||||
35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2,
|
||||
2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2,
|
||||
2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2,
|
||||
2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3,
|
||||
2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73,
|
||||
3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 3,
|
||||
82, 3, 2, 2, 2, 5, 89, 3, 2, 2, 2, 7, 93, 3, 2, 2, 2, 9, 106, 3, 2, 2,
|
||||
2, 11, 119, 3, 2, 2, 2, 13, 121, 3, 2, 2, 2, 15, 128, 3, 2, 2, 2, 17, 130,
|
||||
3, 2, 2, 2, 19, 132, 3, 2, 2, 2, 21, 134, 3, 2, 2, 2, 23, 136, 3, 2, 2,
|
||||
2, 25, 140, 3, 2, 2, 2, 27, 142, 3, 2, 2, 2, 29, 146, 3, 2, 2, 2, 31, 149,
|
||||
3, 2, 2, 2, 33, 153, 3, 2, 2, 2, 35, 157, 3, 2, 2, 2, 37, 159, 3, 2, 2,
|
||||
2, 39, 161, 3, 2, 2, 2, 41, 163, 3, 2, 2, 2, 43, 165, 3, 2, 2, 2, 45, 167,
|
||||
3, 2, 2, 2, 47, 169, 3, 2, 2, 2, 49, 172, 3, 2, 2, 2, 51, 174, 3, 2, 2,
|
||||
2, 53, 177, 3, 2, 2, 2, 55, 179, 3, 2, 2, 2, 57, 182, 3, 2, 2, 2, 59, 185,
|
||||
3, 2, 2, 2, 61, 190, 3, 2, 2, 2, 63, 197, 3, 2, 2, 2, 65, 200, 3, 2, 2,
|
||||
2, 67, 205, 3, 2, 2, 2, 69, 211, 3, 2, 2, 2, 71, 213, 3, 2, 2, 2, 73, 216,
|
||||
3, 2, 2, 2, 75, 221, 3, 2, 2, 2, 77, 226, 3, 2, 2, 2, 79, 230, 3, 2, 2,
|
||||
2, 81, 83, 9, 2, 2, 2, 82, 81, 3, 2, 2, 2, 83, 84, 3, 2, 2, 2, 84, 82,
|
||||
3, 2, 2, 2, 84, 85, 3, 2, 2, 2, 85, 86, 3, 2, 2, 2, 86, 87, 8, 2, 2, 2,
|
||||
87, 4, 3, 2, 2, 2, 88, 90, 9, 3, 2, 2, 89, 88, 3, 2, 2, 2, 90, 91, 3, 2,
|
||||
2, 2, 91, 89, 3, 2, 2, 2, 91, 92, 3, 2, 2, 2, 92, 6, 3, 2, 2, 2, 93, 101,
|
||||
7, 36, 2, 2, 94, 95, 7, 94, 2, 2, 95, 100, 11, 2, 2, 2, 96, 97, 7, 36,
|
||||
2, 2, 97, 100, 7, 36, 2, 2, 98, 100, 10, 4, 2, 2, 99, 94, 3, 2, 2, 2, 99,
|
||||
96, 3, 2, 2, 2, 99, 98, 3, 2, 2, 2, 100, 103, 3, 2, 2, 2, 101, 99, 3, 2,
|
||||
2, 2, 101, 102, 3, 2, 2, 2, 102, 104, 3, 2, 2, 2, 103, 101, 3, 2, 2, 2,
|
||||
104, 105, 7, 36, 2, 2, 105, 8, 3, 2, 2, 2, 106, 114, 7, 41, 2, 2, 107,
|
||||
108, 7, 94, 2, 2, 108, 113, 11, 2, 2, 2, 109, 110, 7, 41, 2, 2, 110, 113,
|
||||
7, 41, 2, 2, 111, 113, 10, 5, 2, 2, 112, 107, 3, 2, 2, 2, 112, 109, 3,
|
||||
2, 2, 2, 112, 111, 3, 2, 2, 2, 113, 116, 3, 2, 2, 2, 114, 112, 3, 2, 2,
|
||||
2, 114, 115, 3, 2, 2, 2, 115, 117, 3, 2, 2, 2, 116, 114, 3, 2, 2, 2, 117,
|
||||
118, 7, 41, 2, 2, 118, 10, 3, 2, 2, 2, 119, 120, 9, 6, 2, 2, 120, 12, 3,
|
||||
2, 2, 2, 121, 125, 9, 7, 2, 2, 122, 124, 9, 8, 2, 2, 123, 122, 3, 2, 2,
|
||||
2, 124, 127, 3, 2, 2, 2, 125, 123, 3, 2, 2, 2, 125, 126, 3, 2, 2, 2, 126,
|
||||
14, 3, 2, 2, 2, 127, 125, 3, 2, 2, 2, 128, 129, 7, 42, 2, 2, 129, 16, 3,
|
||||
2, 2, 2, 130, 131, 7, 43, 2, 2, 131, 18, 3, 2, 2, 2, 132, 133, 7, 46, 2,
|
||||
2, 133, 20, 3, 2, 2, 2, 134, 135, 7, 41, 2, 2, 135, 22, 3, 2, 2, 2, 136,
|
||||
137, 7, 36, 2, 2, 137, 24, 3, 2, 2, 2, 138, 141, 5, 21, 11, 2, 139, 141,
|
||||
5, 23, 12, 2, 140, 138, 3, 2, 2, 2, 140, 139, 3, 2, 2, 2, 141, 26, 3, 2,
|
||||
2, 2, 142, 143, 7, 67, 2, 2, 143, 144, 7, 80, 2, 2, 144, 145, 7, 70, 2,
|
||||
2, 145, 28, 3, 2, 2, 2, 146, 147, 7, 81, 2, 2, 147, 148, 7, 84, 2, 2, 148,
|
||||
30, 3, 2, 2, 2, 149, 150, 7, 90, 2, 2, 150, 151, 7, 81, 2, 2, 151, 152,
|
||||
7, 84, 2, 2, 152, 32, 3, 2, 2, 2, 153, 154, 7, 80, 2, 2, 154, 155, 7, 81,
|
||||
2, 2, 155, 156, 7, 86, 2, 2, 156, 34, 3, 2, 2, 2, 157, 158, 7, 44, 2, 2,
|
||||
158, 36, 3, 2, 2, 2, 159, 160, 7, 49, 2, 2, 160, 38, 3, 2, 2, 2, 161, 162,
|
||||
7, 39, 2, 2, 162, 40, 3, 2, 2, 2, 163, 164, 7, 45, 2, 2, 164, 42, 3, 2,
|
||||
2, 2, 165, 166, 7, 47, 2, 2, 166, 44, 3, 2, 2, 2, 167, 168, 7, 63, 2, 2,
|
||||
168, 46, 3, 2, 2, 2, 169, 170, 7, 35, 2, 2, 170, 171, 7, 63, 2, 2, 171,
|
||||
48, 3, 2, 2, 2, 172, 173, 7, 64, 2, 2, 173, 50, 3, 2, 2, 2, 174, 175, 7,
|
||||
64, 2, 2, 175, 176, 7, 63, 2, 2, 176, 52, 3, 2, 2, 2, 177, 178, 7, 62,
|
||||
2, 2, 178, 54, 3, 2, 2, 2, 179, 180, 7, 62, 2, 2, 180, 181, 7, 64, 2, 2,
|
||||
181, 56, 3, 2, 2, 2, 182, 183, 7, 62, 2, 2, 183, 184, 7, 63, 2, 2, 184,
|
||||
58, 3, 2, 2, 2, 185, 186, 7, 78, 2, 2, 186, 187, 7, 75, 2, 2, 187, 188,
|
||||
7, 77, 2, 2, 188, 189, 7, 71, 2, 2, 189, 60, 3, 2, 2, 2, 190, 191, 7, 71,
|
||||
2, 2, 191, 192, 7, 90, 2, 2, 192, 193, 7, 75, 2, 2, 193, 194, 7, 85, 2,
|
||||
2, 194, 195, 7, 86, 2, 2, 195, 196, 7, 85, 2, 2, 196, 62, 3, 2, 2, 2, 197,
|
||||
198, 7, 75, 2, 2, 198, 199, 7, 80, 2, 2, 199, 64, 3, 2, 2, 2, 200, 201,
|
||||
7, 86, 2, 2, 201, 202, 7, 84, 2, 2, 202, 203, 7, 87, 2, 2, 203, 204, 7,
|
||||
71, 2, 2, 204, 66, 3, 2, 2, 2, 205, 206, 7, 72, 2, 2, 206, 207, 7, 67,
|
||||
2, 2, 207, 208, 7, 78, 2, 2, 208, 209, 7, 85, 2, 2, 209, 210, 7, 71, 2,
|
||||
2, 210, 68, 3, 2, 2, 2, 211, 212, 5, 7, 4, 2, 212, 70, 3, 2, 2, 2, 213,
|
||||
214, 5, 9, 5, 2, 214, 72, 3, 2, 2, 2, 215, 217, 5, 11, 6, 2, 216, 215,
|
||||
3, 2, 2, 2, 217, 218, 3, 2, 2, 2, 218, 216, 3, 2, 2, 2, 218, 219, 3, 2,
|
||||
2, 2, 219, 74, 3, 2, 2, 2, 220, 222, 9, 9, 2, 2, 221, 220, 3, 2, 2, 2,
|
||||
222, 223, 3, 2, 2, 2, 223, 221, 3, 2, 2, 2, 223, 224, 3, 2, 2, 2, 224,
|
||||
76, 3, 2, 2, 2, 225, 227, 9, 3, 2, 2, 226, 225, 3, 2, 2, 2, 227, 228, 3,
|
||||
2, 2, 2, 228, 226, 3, 2, 2, 2, 228, 229, 3, 2, 2, 2, 229, 78, 3, 2, 2,
|
||||
2, 230, 234, 9, 7, 2, 2, 231, 233, 9, 8, 2, 2, 232, 231, 3, 2, 2, 2, 233,
|
||||
236, 3, 2, 2, 2, 234, 232, 3, 2, 2, 2, 234, 235, 3, 2, 2, 2, 235, 80, 3,
|
||||
2, 2, 2, 236, 234, 3, 2, 2, 2, 15, 2, 84, 91, 99, 101, 112, 114, 125, 140,
|
||||
218, 223, 228, 234, 3, 8, 2, 2,
|
||||
}
|
||||
|
||||
var lexerChannelNames = []string{
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
|
||||
}
|
||||
|
||||
var lexerModeNames = []string{
|
||||
"DEFAULT_MODE",
|
||||
}
|
||||
|
||||
var lexerLiteralNames = []string{
|
||||
"", "", "'('", "')'", "','", "'''", "'\"'", "'AND'", "'OR'", "'XOR'", "'NOT'",
|
||||
"'*'", "'/'", "'%'", "'+'", "'-'", "'='", "'!='", "'>'", "'>='", "'<'",
|
||||
"'<>'", "'<='", "'LIKE'", "'EXISTS'", "'IN'", "'TRUE'", "'FALSE'",
|
||||
}
|
||||
|
||||
var lexerSymbolicNames = []string{
|
||||
"", "SPACE", "LR_BRACKET", "RR_BRACKET", "COMMA", "SINGLE_QUOTE_SYMB",
|
||||
"DOUBLE_QUOTE_SYMB", "AND", "OR", "XOR", "NOT", "STAR", "DIVIDE", "MODULE",
|
||||
"PLUS", "MINUS", "EQUAL", "NOT_EQUAL", "GREATER", "GREATER_OR_EQUAL", "LESS",
|
||||
"LESS_GREATER", "LESS_OR_EQUAL", "LIKE", "EXISTS", "IN", "TRUE", "FALSE",
|
||||
"DQUOTED_STRING_LITERAL", "SQUOTED_STRING_LITERAL", "INTEGER_LITERAL",
|
||||
"IDENTIFIER", "IDENTIFIER_WITH_NUMBER", "FUNCTION_IDENTIFIER_WITH_UNDERSCORE",
|
||||
}
|
||||
|
||||
var lexerRuleNames = []string{
|
||||
"SPACE", "ID_LITERAL", "DQUOTA_STRING", "SQUOTA_STRING", "INT_DIGIT", "FN_LITERAL",
|
||||
"LR_BRACKET", "RR_BRACKET", "COMMA", "SINGLE_QUOTE_SYMB", "DOUBLE_QUOTE_SYMB",
|
||||
"QUOTE_SYMB", "AND", "OR", "XOR", "NOT", "STAR", "DIVIDE", "MODULE", "PLUS",
|
||||
"MINUS", "EQUAL", "NOT_EQUAL", "GREATER", "GREATER_OR_EQUAL", "LESS", "LESS_GREATER",
|
||||
"LESS_OR_EQUAL", "LIKE", "EXISTS", "IN", "TRUE", "FALSE", "DQUOTED_STRING_LITERAL",
|
||||
"SQUOTED_STRING_LITERAL", "INTEGER_LITERAL", "IDENTIFIER", "IDENTIFIER_WITH_NUMBER",
|
||||
"FUNCTION_IDENTIFIER_WITH_UNDERSCORE",
|
||||
}
|
||||
|
||||
type CESQLParserLexer struct {
|
||||
*antlr.BaseLexer
|
||||
channelNames []string
|
||||
modeNames []string
|
||||
// TODO: EOF string
|
||||
}
|
||||
|
||||
// NewCESQLParserLexer produces a new lexer instance for the optional input antlr.CharStream.
|
||||
//
|
||||
// The *CESQLParserLexer instance produced may be reused by calling the SetInputStream method.
|
||||
// The initial lexer configuration is expensive to construct, and the object is not thread-safe;
|
||||
// however, if used within a Golang sync.Pool, the construction cost amortizes well and the
|
||||
// objects can be used in a thread-safe manner.
|
||||
func NewCESQLParserLexer(input antlr.CharStream) *CESQLParserLexer {
|
||||
l := new(CESQLParserLexer)
|
||||
lexerDeserializer := antlr.NewATNDeserializer(nil)
|
||||
lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
|
||||
lexerDecisionToDFA := make([]*antlr.DFA, len(lexerAtn.DecisionToState))
|
||||
for index, ds := range lexerAtn.DecisionToState {
|
||||
lexerDecisionToDFA[index] = antlr.NewDFA(ds, index)
|
||||
}
|
||||
l.BaseLexer = antlr.NewBaseLexer(input)
|
||||
l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache())
|
||||
|
||||
l.channelNames = lexerChannelNames
|
||||
l.modeNames = lexerModeNames
|
||||
l.RuleNames = lexerRuleNames
|
||||
l.LiteralNames = lexerLiteralNames
|
||||
l.SymbolicNames = lexerSymbolicNames
|
||||
l.GrammarFileName = "CESQLParser.g4"
|
||||
// TODO: l.EOF = antlr.TokenEOF
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
// CESQLParserLexer tokens.
|
||||
const (
|
||||
CESQLParserLexerSPACE = 1
|
||||
CESQLParserLexerLR_BRACKET = 2
|
||||
CESQLParserLexerRR_BRACKET = 3
|
||||
CESQLParserLexerCOMMA = 4
|
||||
CESQLParserLexerSINGLE_QUOTE_SYMB = 5
|
||||
CESQLParserLexerDOUBLE_QUOTE_SYMB = 6
|
||||
CESQLParserLexerAND = 7
|
||||
CESQLParserLexerOR = 8
|
||||
CESQLParserLexerXOR = 9
|
||||
CESQLParserLexerNOT = 10
|
||||
CESQLParserLexerSTAR = 11
|
||||
CESQLParserLexerDIVIDE = 12
|
||||
CESQLParserLexerMODULE = 13
|
||||
CESQLParserLexerPLUS = 14
|
||||
CESQLParserLexerMINUS = 15
|
||||
CESQLParserLexerEQUAL = 16
|
||||
CESQLParserLexerNOT_EQUAL = 17
|
||||
CESQLParserLexerGREATER = 18
|
||||
CESQLParserLexerGREATER_OR_EQUAL = 19
|
||||
CESQLParserLexerLESS = 20
|
||||
CESQLParserLexerLESS_GREATER = 21
|
||||
CESQLParserLexerLESS_OR_EQUAL = 22
|
||||
CESQLParserLexerLIKE = 23
|
||||
CESQLParserLexerEXISTS = 24
|
||||
CESQLParserLexerIN = 25
|
||||
CESQLParserLexerTRUE = 26
|
||||
CESQLParserLexerFALSE = 27
|
||||
CESQLParserLexerDQUOTED_STRING_LITERAL = 28
|
||||
CESQLParserLexerSQUOTED_STRING_LITERAL = 29
|
||||
CESQLParserLexerINTEGER_LITERAL = 30
|
||||
CESQLParserLexerIDENTIFIER = 31
|
||||
CESQLParserLexerIDENTIFIER_WITH_NUMBER = 32
|
||||
CESQLParserLexerFUNCTION_IDENTIFIER_WITH_UNDERSCORE = 33
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// Code generated from CESQLParser.g4 by ANTLR 4.9. DO NOT EDIT.
|
||||
|
||||
package gen // CESQLParser
|
||||
import "github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
|
||||
// A complete Visitor for a parse tree produced by CESQLParserParser.
|
||||
type CESQLParserVisitor interface {
|
||||
antlr.ParseTreeVisitor
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#cesql.
|
||||
VisitCesql(ctx *CesqlContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#inExpression.
|
||||
VisitInExpression(ctx *InExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#binaryComparisonExpression.
|
||||
VisitBinaryComparisonExpression(ctx *BinaryComparisonExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#atomExpression.
|
||||
VisitAtomExpression(ctx *AtomExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#existsExpression.
|
||||
VisitExistsExpression(ctx *ExistsExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#binaryLogicExpression.
|
||||
VisitBinaryLogicExpression(ctx *BinaryLogicExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#likeExpression.
|
||||
VisitLikeExpression(ctx *LikeExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#functionInvocationExpression.
|
||||
VisitFunctionInvocationExpression(ctx *FunctionInvocationExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#binaryMultiplicativeExpression.
|
||||
VisitBinaryMultiplicativeExpression(ctx *BinaryMultiplicativeExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#unaryLogicExpression.
|
||||
VisitUnaryLogicExpression(ctx *UnaryLogicExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#unaryNumericExpression.
|
||||
VisitUnaryNumericExpression(ctx *UnaryNumericExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#subExpression.
|
||||
VisitSubExpression(ctx *SubExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#binaryAdditiveExpression.
|
||||
VisitBinaryAdditiveExpression(ctx *BinaryAdditiveExpressionContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#booleanAtom.
|
||||
VisitBooleanAtom(ctx *BooleanAtomContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#integerAtom.
|
||||
VisitIntegerAtom(ctx *IntegerAtomContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#stringAtom.
|
||||
VisitStringAtom(ctx *StringAtomContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#identifierAtom.
|
||||
VisitIdentifierAtom(ctx *IdentifierAtomContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#identifier.
|
||||
VisitIdentifier(ctx *IdentifierContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#functionIdentifier.
|
||||
VisitFunctionIdentifier(ctx *FunctionIdentifierContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#booleanLiteral.
|
||||
VisitBooleanLiteral(ctx *BooleanLiteralContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#stringLiteral.
|
||||
VisitStringLiteral(ctx *StringLiteralContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#integerLiteral.
|
||||
VisitIntegerLiteral(ctx *IntegerLiteralContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#functionParameterList.
|
||||
VisitFunctionParameterList(ctx *FunctionParameterListContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by CESQLParserParser#setExpression.
|
||||
VisitSetExpression(ctx *SetExpressionContext) interface{}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
module github.com/cloudevents/sdk-go/sql/v2
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/antlr/antlr4 v0.0.0-20210105192202-5c2b686f95e1
|
||||
github.com/cloudevents/sdk-go/v2 v2.4.1
|
||||
github.com/stretchr/testify v1.5.1
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
replace github.com/cloudevents/sdk-go/v2 => ../../v2
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
github.com/antlr/antlr4 v0.0.0-20210105192202-5c2b686f95e1 h1:9K5yytxEEQc4yIn6c1rvQD6qQilQn9mYIF7pXKPT8i4=
|
||||
github.com/antlr/antlr4 v0.0.0-20210105192202-5c2b686f95e1/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
|
||||
github.com/antlr/antlr4 v0.0.0-20210412152734-e404d26f6142 h1:ucCGXTGwxNdEi4/QGohyvI0e3FCsS8cdCW15x2e1bDk=
|
||||
github.com/antlr/antlr4 v0.0.0-20210412152734-e404d26f6142/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
)
|
||||
|
||||
// Took from https://github.com/antlr/antlr4/blob/master/doc/resources/case_changing_stream.go
|
||||
|
||||
// CaseChangingStream wraps an existing CharStream, but upper cases, or
|
||||
// lower cases the input before it is tokenized.
|
||||
type CaseChangingStream struct {
|
||||
antlr.CharStream
|
||||
|
||||
upper bool
|
||||
}
|
||||
|
||||
// NewCaseChangingStream returns a new CaseChangingStream that forces
|
||||
// all tokens read from the underlying stream to be either upper case
|
||||
// or lower case based on the upper argument.
|
||||
func NewCaseChangingStream(in antlr.CharStream, upper bool) *CaseChangingStream {
|
||||
return &CaseChangingStream{in, upper}
|
||||
}
|
||||
|
||||
// LA gets the value of the symbol at offset from the current position
|
||||
// from the underlying CharStream and converts it to either upper case
|
||||
// or lower case.
|
||||
func (is *CaseChangingStream) LA(offset int) int {
|
||||
in := is.CharStream.LA(offset)
|
||||
if in < 0 {
|
||||
// Such as antlr.TokenEOF which is -1
|
||||
return in
|
||||
}
|
||||
if is.upper {
|
||||
return int(unicode.ToUpper(rune(in)))
|
||||
}
|
||||
return int(unicode.ToLower(rune(in)))
|
||||
}
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/expression"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/gen"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
)
|
||||
|
||||
type expressionVisitor struct {
|
||||
parsingErrors []error
|
||||
}
|
||||
|
||||
var _ gen.CESQLParserVisitor = (*expressionVisitor)(nil)
|
||||
|
||||
func NewExpressionVisitor() gen.CESQLParserVisitor {
|
||||
return &expressionVisitor{}
|
||||
}
|
||||
|
||||
// antlr.ParseTreeVisitor implementation
|
||||
|
||||
func (v *expressionVisitor) Visit(tree antlr.ParseTree) interface{} {
|
||||
// If you're wondering why I had to manually implement this stuff:
|
||||
// https://github.com/antlr/antlr4/issues/2504
|
||||
switch tree.(type) {
|
||||
case *gen.CesqlContext:
|
||||
return v.VisitCesql(tree.(*gen.CesqlContext))
|
||||
case *gen.AtomExpressionContext:
|
||||
return v.VisitAtomExpression(tree.(*gen.AtomExpressionContext))
|
||||
case *gen.UnaryNumericExpressionContext:
|
||||
return v.VisitUnaryNumericExpression(tree.(*gen.UnaryNumericExpressionContext))
|
||||
case *gen.UnaryLogicExpressionContext:
|
||||
return v.VisitUnaryLogicExpression(tree.(*gen.UnaryLogicExpressionContext))
|
||||
case *gen.BooleanAtomContext:
|
||||
return v.VisitBooleanAtom(tree.(*gen.BooleanAtomContext))
|
||||
case *gen.BooleanLiteralContext:
|
||||
return v.VisitBooleanLiteral(tree.(*gen.BooleanLiteralContext))
|
||||
case *gen.IntegerAtomContext:
|
||||
return v.VisitIntegerAtom(tree.(*gen.IntegerAtomContext))
|
||||
case *gen.IntegerLiteralContext:
|
||||
return v.VisitIntegerLiteral(tree.(*gen.IntegerLiteralContext))
|
||||
case *gen.StringAtomContext:
|
||||
return v.VisitStringAtom(tree.(*gen.StringAtomContext))
|
||||
case *gen.StringLiteralContext:
|
||||
return v.VisitStringLiteral(tree.(*gen.StringLiteralContext))
|
||||
case *gen.ExistsExpressionContext:
|
||||
return v.VisitExistsExpression(tree.(*gen.ExistsExpressionContext))
|
||||
case *gen.InExpressionContext:
|
||||
return v.VisitInExpression(tree.(*gen.InExpressionContext))
|
||||
case *gen.IdentifierAtomContext:
|
||||
return v.VisitIdentifierAtom(tree.(*gen.IdentifierAtomContext))
|
||||
case *gen.IdentifierContext:
|
||||
return v.VisitIdentifier(tree.(*gen.IdentifierContext))
|
||||
case *gen.BinaryMultiplicativeExpressionContext:
|
||||
return v.VisitBinaryMultiplicativeExpression(tree.(*gen.BinaryMultiplicativeExpressionContext))
|
||||
case *gen.BinaryAdditiveExpressionContext:
|
||||
return v.VisitBinaryAdditiveExpression(tree.(*gen.BinaryAdditiveExpressionContext))
|
||||
case *gen.SubExpressionContext:
|
||||
return v.VisitSubExpression(tree.(*gen.SubExpressionContext))
|
||||
case *gen.BinaryLogicExpressionContext:
|
||||
return v.VisitBinaryLogicExpression(tree.(*gen.BinaryLogicExpressionContext))
|
||||
case *gen.BinaryComparisonExpressionContext:
|
||||
return v.VisitBinaryComparisonExpression(tree.(*gen.BinaryComparisonExpressionContext))
|
||||
case *gen.LikeExpressionContext:
|
||||
return v.VisitLikeExpression(tree.(*gen.LikeExpressionContext))
|
||||
case *gen.FunctionInvocationExpressionContext:
|
||||
return v.VisitFunctionInvocationExpression(tree.(*gen.FunctionInvocationExpressionContext))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitChildren(node antlr.RuleNode) interface{} {
|
||||
return v.Visit(node.GetChild(0).(antlr.ParseTree))
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitTerminal(node antlr.TerminalNode) interface{} {
|
||||
// We never visit terminal nodes
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitErrorNode(node antlr.ErrorNode) interface{} {
|
||||
// We already collect errors using the error listener
|
||||
return nil
|
||||
}
|
||||
|
||||
// gen.CESQLParserVisitor implementation
|
||||
|
||||
func (v *expressionVisitor) VisitInExpression(ctx *gen.InExpressionContext) interface{} {
|
||||
leftExpression := v.Visit(ctx.Expression()).(cesql.Expression)
|
||||
|
||||
var setExpression []cesql.Expression
|
||||
|
||||
for _, expr := range ctx.SetExpression().(*gen.SetExpressionContext).AllExpression() {
|
||||
setExpression = append(setExpression, v.Visit(expr).(cesql.Expression))
|
||||
}
|
||||
|
||||
if ctx.NOT() != nil {
|
||||
return expression.NewNotExpression(expression.NewInExpression(leftExpression, setExpression))
|
||||
}
|
||||
|
||||
return expression.NewInExpression(leftExpression, setExpression)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitBinaryComparisonExpression(ctx *gen.BinaryComparisonExpressionContext) interface{} {
|
||||
if ctx.LESS() != nil {
|
||||
return expression.NewLessExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else if ctx.LESS_OR_EQUAL() != nil {
|
||||
return expression.NewLessOrEqualExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else if ctx.GREATER() != nil {
|
||||
return expression.NewGreaterExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else if ctx.GREATER_OR_EQUAL() != nil {
|
||||
return expression.NewGreaterOrEqualExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else if ctx.EQUAL() != nil {
|
||||
return expression.NewEqualExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else {
|
||||
return expression.NewNotEqualExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitExistsExpression(ctx *gen.ExistsExpressionContext) interface{} {
|
||||
return expression.NewExistsExpression(strings.ToLower(ctx.Identifier().GetText()))
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitBinaryLogicExpression(ctx *gen.BinaryLogicExpressionContext) interface{} {
|
||||
if ctx.AND() != nil {
|
||||
return expression.NewAndExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else if ctx.OR() != nil {
|
||||
return expression.NewOrExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else {
|
||||
return expression.NewXorExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitLikeExpression(ctx *gen.LikeExpressionContext) interface{} {
|
||||
patternContext := ctx.StringLiteral().(*gen.StringLiteralContext)
|
||||
|
||||
var pattern string
|
||||
if patternContext.DQUOTED_STRING_LITERAL() != nil {
|
||||
// Parse double quoted string
|
||||
pattern = dQuotedStringToString(patternContext.DQUOTED_STRING_LITERAL().GetText())
|
||||
} else {
|
||||
// Parse single quoted string
|
||||
pattern = sQuotedStringToString(patternContext.SQUOTED_STRING_LITERAL().GetText())
|
||||
}
|
||||
|
||||
likeExpression, err := expression.NewLikeExpression(v.Visit(ctx.Expression()).(cesql.Expression), pattern)
|
||||
if err != nil {
|
||||
v.parsingErrors = append(v.parsingErrors, err)
|
||||
return noopExpression{}
|
||||
}
|
||||
|
||||
if ctx.NOT() != nil {
|
||||
return expression.NewNotExpression(likeExpression)
|
||||
}
|
||||
|
||||
return likeExpression
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitFunctionInvocationExpression(ctx *gen.FunctionInvocationExpressionContext) interface{} {
|
||||
paramsCtx := ctx.FunctionParameterList().(*gen.FunctionParameterListContext)
|
||||
|
||||
name := ctx.FunctionIdentifier().GetText()
|
||||
|
||||
var args []cesql.Expression
|
||||
for _, expr := range paramsCtx.AllExpression() {
|
||||
args = append(args, v.Visit(expr).(cesql.Expression))
|
||||
}
|
||||
|
||||
return expression.NewFunctionInvocationExpression(strings.ToUpper(name), args)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitBinaryMultiplicativeExpression(ctx *gen.BinaryMultiplicativeExpressionContext) interface{} {
|
||||
if ctx.STAR() != nil {
|
||||
return expression.NewMultiplicationExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else if ctx.MODULE() != nil {
|
||||
return expression.NewModuleExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else {
|
||||
return expression.NewDivisionExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitUnaryLogicExpression(ctx *gen.UnaryLogicExpressionContext) interface{} {
|
||||
return expression.NewNotExpression(
|
||||
v.Visit(ctx.Expression()).(cesql.Expression),
|
||||
)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitUnaryNumericExpression(ctx *gen.UnaryNumericExpressionContext) interface{} {
|
||||
return expression.NewNegateExpression(
|
||||
v.Visit(ctx.Expression()).(cesql.Expression),
|
||||
)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitSubExpression(ctx *gen.SubExpressionContext) interface{} {
|
||||
return v.Visit(ctx.Expression())
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitBinaryAdditiveExpression(ctx *gen.BinaryAdditiveExpressionContext) interface{} {
|
||||
if ctx.PLUS() != nil {
|
||||
return expression.NewSumExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
} else {
|
||||
return expression.NewDifferenceExpression(
|
||||
v.Visit(ctx.Expression(0)).(cesql.Expression),
|
||||
v.Visit(ctx.Expression(1)).(cesql.Expression),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitIdentifier(ctx *gen.IdentifierContext) interface{} {
|
||||
return expression.NewIdentifierExpression(strings.ToLower(ctx.GetText()))
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitBooleanLiteral(ctx *gen.BooleanLiteralContext) interface{} {
|
||||
return expression.NewLiteralExpression(ctx.TRUE() != nil)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitStringLiteral(ctx *gen.StringLiteralContext) interface{} {
|
||||
var str string
|
||||
if ctx.DQUOTED_STRING_LITERAL() != nil {
|
||||
// Parse double quoted string
|
||||
str = dQuotedStringToString(ctx.DQUOTED_STRING_LITERAL().GetText())
|
||||
} else {
|
||||
// Parse single quoted string
|
||||
str = sQuotedStringToString(ctx.SQUOTED_STRING_LITERAL().GetText())
|
||||
}
|
||||
|
||||
return expression.NewLiteralExpression(str)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitIntegerLiteral(ctx *gen.IntegerLiteralContext) interface{} {
|
||||
val, err := strconv.Atoi(ctx.GetText())
|
||||
if err != nil {
|
||||
v.parsingErrors = append(v.parsingErrors, err)
|
||||
}
|
||||
return expression.NewLiteralExpression(int32(val))
|
||||
}
|
||||
|
||||
// gen.CESQLParserVisitor implementation - noop methods
|
||||
|
||||
func (v *expressionVisitor) VisitCesql(ctx *gen.CesqlContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitAtomExpression(ctx *gen.AtomExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitBooleanAtom(ctx *gen.BooleanAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitIntegerAtom(ctx *gen.IntegerAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitStringAtom(ctx *gen.StringAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitIdentifierAtom(ctx *gen.IdentifierAtomContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitSetExpression(ctx *gen.SetExpressionContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitFunctionIdentifier(ctx *gen.FunctionIdentifierContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *expressionVisitor) VisitFunctionParameterList(ctx *gen.FunctionParameterListContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
// noop expression. This is necessary to continue to walk through the tree, even if there's a failure in the parsing
|
||||
|
||||
type noopExpression struct{}
|
||||
|
||||
func (n noopExpression) Evaluate(cloudevents.Event) (interface{}, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
func dQuotedStringToString(str string) string {
|
||||
str = str[1 : len(str)-1]
|
||||
return strings.ReplaceAll(str, "\\\"", "\"")
|
||||
}
|
||||
|
||||
func sQuotedStringToString(str string) string {
|
||||
str = str[1 : len(str)-1]
|
||||
return strings.ReplaceAll(str, "\\'", "'")
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package parser
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr"
|
||||
|
||||
"github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/gen"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
// TODO parser options
|
||||
}
|
||||
|
||||
func (p *Parser) Parse(input string) (v2.Expression, error) {
|
||||
var is antlr.CharStream = antlr.NewInputStream(input)
|
||||
is = NewCaseChangingStream(is, true)
|
||||
|
||||
// Create the JSON Lexer
|
||||
lexer := gen.NewCESQLParserLexer(is)
|
||||
var stream antlr.TokenStream = antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
|
||||
|
||||
// Create the JSON Parser
|
||||
antlrParser := gen.NewCESQLParserParser(stream)
|
||||
antlrParser.RemoveErrorListeners()
|
||||
collectingErrorListener := errorListener{}
|
||||
antlrParser.AddErrorListener(&collectingErrorListener)
|
||||
|
||||
// Finally walk the tree
|
||||
visitor := expressionVisitor{}
|
||||
result := antlrParser.Cesql().Accept(&visitor)
|
||||
|
||||
if result == nil {
|
||||
return nil, mergeErrs(append(collectingErrorListener.errs, visitor.parsingErrors...))
|
||||
}
|
||||
|
||||
return result.(v2.Expression), mergeErrs(append(collectingErrorListener.errs, visitor.parsingErrors...))
|
||||
}
|
||||
|
||||
type errorListener struct {
|
||||
antlr.DefaultErrorListener
|
||||
errs []error
|
||||
}
|
||||
|
||||
func (d *errorListener) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) {
|
||||
d.errs = append(d.errs, fmt.Errorf("syntax error: %v", e.GetMessage()))
|
||||
}
|
||||
|
||||
func mergeErrs(errs []error) error {
|
||||
if len(errs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errStrings []string
|
||||
for _, err := range errs {
|
||||
errStrings = append(errStrings, err.Error())
|
||||
}
|
||||
|
||||
return errors.New(strings.Join(errStrings, ","))
|
||||
}
|
||||
|
||||
var defaultParser = Parser{}
|
||||
|
||||
func Parse(input string) (v2.Expression, error) {
|
||||
return defaultParser.Parse(input)
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
"github.com/cloudevents/sdk-go/sql/v2/function"
|
||||
)
|
||||
|
||||
type functionItem struct {
|
||||
fixedArgsFunctions map[int]cesql.Function
|
||||
variadicFunction cesql.Function
|
||||
}
|
||||
|
||||
type functionTable map[string]*functionItem
|
||||
|
||||
func (table functionTable) AddFunction(function cesql.Function) error {
|
||||
item := table[function.Name()]
|
||||
if item == nil {
|
||||
item = &functionItem{
|
||||
fixedArgsFunctions: make(map[int]cesql.Function),
|
||||
}
|
||||
table[function.Name()] = item
|
||||
}
|
||||
|
||||
if function.IsVariadic() {
|
||||
if item.variadicFunction != nil {
|
||||
return errors.New("cannot add the variadic function, " +
|
||||
"because there is already another variadic function defined with the same name")
|
||||
}
|
||||
maxArity := -1
|
||||
for a := range item.fixedArgsFunctions {
|
||||
if a > maxArity {
|
||||
maxArity = a
|
||||
}
|
||||
}
|
||||
if maxArity >= function.Arity() {
|
||||
return errors.New("cannot add the variadic function, " +
|
||||
"because there is already another function defined with the same name and same or greater arity")
|
||||
}
|
||||
|
||||
item.variadicFunction = function
|
||||
return nil
|
||||
} else {
|
||||
if _, ok := item.fixedArgsFunctions[function.Arity()]; ok {
|
||||
return errors.New("cannot add the function, " +
|
||||
"because there is already another function defined with the same arity and same name")
|
||||
}
|
||||
|
||||
item.fixedArgsFunctions[function.Arity()] = function
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (table functionTable) ResolveFunction(name string, args int) cesql.Function {
|
||||
item := table[strings.ToUpper(name)]
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if fn, ok := item.fixedArgsFunctions[args]; ok {
|
||||
return fn
|
||||
}
|
||||
|
||||
if item.variadicFunction == nil || item.variadicFunction.Arity() > args {
|
||||
return nil
|
||||
}
|
||||
|
||||
return item.variadicFunction
|
||||
}
|
||||
|
||||
var globalFunctionTable = functionTable{}
|
||||
|
||||
func init() {
|
||||
for _, fn := range []cesql.Function{
|
||||
function.IntFunction,
|
||||
function.BoolFunction,
|
||||
function.StringFunction,
|
||||
function.IsBoolFunction,
|
||||
function.IsIntFunction,
|
||||
function.AbsFunction,
|
||||
function.LengthFunction,
|
||||
function.ConcatFunction,
|
||||
function.ConcatWSFunction,
|
||||
function.LowerFunction,
|
||||
function.UpperFunction,
|
||||
function.TrimFunction,
|
||||
function.LeftFunction,
|
||||
function.RightFunction,
|
||||
function.SubstringFunction,
|
||||
function.SubstringWithLengthFunction,
|
||||
} {
|
||||
if err := globalFunctionTable.AddFunction(fn); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ResolveFunction(name string, args int) cesql.Function {
|
||||
return globalFunctionTable.ResolveFunction(name, args)
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
name: Binary comparison operations
|
||||
tests:
|
||||
- name: True is equal to false
|
||||
expression: TRUE = FALSE
|
||||
result: false
|
||||
- name: False is equal to false
|
||||
expression: FALSE = FALSE
|
||||
result: true
|
||||
- name: 1 is equal to 2
|
||||
expression: 1 = 2
|
||||
result: false
|
||||
- name: 2 is equal to 2
|
||||
expression: 2 = 2
|
||||
result: true
|
||||
- name: abc is equal to 123
|
||||
expression: "'abc' = '123'"
|
||||
result: false
|
||||
- name: abc is equal to abc
|
||||
expression: "'abc' = 'abc'"
|
||||
result: true
|
||||
|
||||
- name: True is not equal to false
|
||||
expression: TRUE != FALSE
|
||||
result: true
|
||||
- name: False is not equal to false
|
||||
expression: FALSE != FALSE
|
||||
result: false
|
||||
- name: 1 is not equal to 2
|
||||
expression: 1 != 2
|
||||
result: true
|
||||
- name: 2 is not equal to 2
|
||||
expression: 2 != 2
|
||||
result: false
|
||||
- name: abc is not equal to 123
|
||||
expression: "'abc' != '123'"
|
||||
result: true
|
||||
- name: abc is not equal to abc
|
||||
expression: "'abc' != 'abc'"
|
||||
result: false
|
||||
|
||||
- name: True is not equal to false (diamond operator)
|
||||
expression: TRUE <> FALSE
|
||||
result: true
|
||||
- name: False is not equal to false (diamond operator)
|
||||
expression: FALSE <> FALSE
|
||||
result: false
|
||||
- name: 1 is not equal to 2 (diamond operator)
|
||||
expression: 1 <> 2
|
||||
result: true
|
||||
- name: 2 is not equal to 2 (diamond operator)
|
||||
expression: 2 <> 2
|
||||
result: false
|
||||
- name: abc is not equal to 123 (diamond operator)
|
||||
expression: "'abc' <> '123'"
|
||||
result: true
|
||||
- name: abc is not equal to abc (diamond operator)
|
||||
expression: "'abc' <> 'abc'"
|
||||
result: false
|
||||
|
||||
- name: 1 is less or equal than 2
|
||||
expression: 2 <= 2
|
||||
result: true
|
||||
- name: 3 is less or equal than 2
|
||||
expression: 3 <= 2
|
||||
result: false
|
||||
- name: 1 is less than 2
|
||||
expression: 1 < 2
|
||||
result: true
|
||||
- name: 2 is less than 2
|
||||
expression: 2 < 2
|
||||
result: false
|
||||
- name: 2 is greater or equal than 2
|
||||
expression: 2 >= 2
|
||||
result: true
|
||||
- name: 2 is greater or equal than 3
|
||||
expression: 2 >= 3
|
||||
result: false
|
||||
- name: 2 is greater than 1
|
||||
expression: 2 > 1
|
||||
result: true
|
||||
- name: 2 is greater than 2
|
||||
expression: 2 > 2
|
||||
result: false
|
||||
|
||||
- name: implicit casting with string as right type
|
||||
expression: "true = 'TRUE'"
|
||||
result: false
|
||||
- name: implicit casting with boolean as right type
|
||||
expression: "'TRUE' = true"
|
||||
result: true
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
name: Binary logical operations
|
||||
tests:
|
||||
- name: False and false
|
||||
expression: FALSE AND FALSE
|
||||
result: false
|
||||
- name: False and true
|
||||
expression: FALSE AND TRUE
|
||||
result: false
|
||||
- name: True and false
|
||||
expression: TRUE AND FALSE
|
||||
result: false
|
||||
- name: True and true
|
||||
expression: TRUE AND TRUE
|
||||
result: true
|
||||
|
||||
- name: False or false
|
||||
expression: FALSE OR FALSE
|
||||
result: false
|
||||
- name: False or true
|
||||
expression: FALSE OR TRUE
|
||||
result: true
|
||||
- name: True or false
|
||||
expression: TRUE OR FALSE
|
||||
result: true
|
||||
- name: True or true
|
||||
expression: TRUE OR TRUE
|
||||
result: true
|
||||
|
||||
- name: False xor false
|
||||
expression: FALSE XOR FALSE
|
||||
result: false
|
||||
- name: False xor true
|
||||
expression: FALSE XOR TRUE
|
||||
result: true
|
||||
- name: True xor false
|
||||
expression: TRUE XOR FALSE
|
||||
result: true
|
||||
- name: True xor true
|
||||
expression: TRUE XOR TRUE
|
||||
result: false
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
name: Binary math operations
|
||||
tests:
|
||||
- name: Operator precedence without parenthesis
|
||||
expression: 4 * 2 + 4 / 2
|
||||
result: 10
|
||||
- name: Operator precedence with parenthesis
|
||||
expression: 4 * (2 + 4) / 2
|
||||
result: 12
|
||||
|
||||
- name: Truncated division
|
||||
expression: 5 / 3
|
||||
result: 1
|
||||
- name: Division by zero returns 0 and fail
|
||||
expression: 5 / 0
|
||||
result: 0
|
||||
error: math
|
||||
- name: Module
|
||||
expression: 5 % 2
|
||||
result: 1
|
||||
- name: Module by zero returns 0 and fail
|
||||
expression: 5 % 0
|
||||
result: 0
|
||||
error: math
|
||||
|
||||
- name: Positive plus positive number
|
||||
expression: 4 + 1
|
||||
result: 5
|
||||
- name: Negative plus positive number
|
||||
expression: -4 + 1
|
||||
result: -3
|
||||
- name: Negative plus Negative number
|
||||
expression: -4 + -1
|
||||
result: -5
|
||||
- name: Positive plus negative number
|
||||
expression: 4 + -1
|
||||
result: 3
|
||||
- name: Positive minus positive number
|
||||
expression: 4 - 1
|
||||
result: 3
|
||||
- name: Negative minus positive number
|
||||
expression: -4 - 1
|
||||
result: -5
|
||||
|
||||
- name: Implicit casting, with left value string
|
||||
expression: "'5' + 3"
|
||||
result: 8
|
||||
- name: Implicit casting, with right value string
|
||||
expression: "5 + '3'"
|
||||
result: 8
|
||||
- name: Implicit casting, with both values string
|
||||
expression: "'5' + '3'"
|
||||
result: 8
|
||||
- name: Implicit casting, with invalid boolean value
|
||||
expression: "5 + TRUE"
|
||||
result: 5
|
||||
error: cast
|
||||
- name: Implicit casting, with invalid string value
|
||||
expression: "'5avc4' + 10"
|
||||
result: 10
|
||||
error: cast
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
name: Case sensitivity
|
||||
tests:
|
||||
- name: TRUE
|
||||
expression: TRUE
|
||||
result: true
|
||||
- name: true
|
||||
expression: true
|
||||
result: true
|
||||
- name: tRuE
|
||||
expression: tRuE
|
||||
result: true
|
||||
|
||||
- name: FALSE
|
||||
expression: FALSE
|
||||
result: false
|
||||
- name: false
|
||||
expression: false
|
||||
result: false
|
||||
- name: FaLsE
|
||||
expression: FaLsE
|
||||
result: false
|
||||
|
||||
- name: String literals casing preserved
|
||||
expression: "'aBcD'"
|
||||
result: aBcD
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
name: Casting functions
|
||||
tests:
|
||||
- name: Cast '1' to integer
|
||||
expression: INT('1')
|
||||
result: 1
|
||||
- name: Cast '-1' to integer
|
||||
expression: INT('-1')
|
||||
result: -1
|
||||
- name: Cast identity 1
|
||||
expression: INT(1)
|
||||
result: 1
|
||||
- name: Cast identity -1
|
||||
expression: INT(-1)
|
||||
result: -1
|
||||
- name: Invalid cast from boolean to int
|
||||
expression: INT(TRUE)
|
||||
result: 0
|
||||
error: cast
|
||||
- name: Invalid cast from string to int
|
||||
expression: INT('ABC')
|
||||
result: 0
|
||||
error: cast
|
||||
|
||||
- name: Cast 'TRUE' to boolean
|
||||
expression: BOOL('TRUE')
|
||||
result: true
|
||||
- name: Cast "false" to boolean
|
||||
expression: BOOL("false")
|
||||
result: false
|
||||
- name: Cast identity TRUE
|
||||
expression: BOOL(TRUE)
|
||||
result: true
|
||||
- name: Cast identity FALSE
|
||||
expression: BOOL(FALSE)
|
||||
result: FALSE
|
||||
- name: Invalid cast from string to boolean
|
||||
expression: BOOL('ABC')
|
||||
result: false
|
||||
error: cast
|
||||
- name: Invalid cast from int to boolean
|
||||
expression: BOOL(1)
|
||||
result: false
|
||||
error: cast
|
||||
|
||||
- name: Cast TRUE to string
|
||||
expression: STRING(TRUE)
|
||||
result: 'true'
|
||||
- name: Cast FALSE to string
|
||||
expression: STRING(FALSE)
|
||||
result: 'false'
|
||||
- name: Cast 1 to string
|
||||
expression: STRING(1)
|
||||
result: '1'
|
||||
- name: Cast -1 to string
|
||||
expression: STRING(-1)
|
||||
result: '-1'
|
||||
- name: Cast identity "abc"
|
||||
expression: STRING("abc")
|
||||
result: "abc"
|
||||
|
||||
- name: "'true' is a boolean"
|
||||
expression: IS_BOOL('true')
|
||||
result: true
|
||||
- name: "'FALSE' is a boolean"
|
||||
expression: IS_BOOL('FALSE')
|
||||
result: true
|
||||
- name: 1 is not a boolean
|
||||
expression: IS_BOOL(1)
|
||||
result: false
|
||||
- name: "'abc' is not a boolean"
|
||||
expression: IS_BOOL('abc')
|
||||
result: false
|
||||
|
||||
- name: "'-1' is an int"
|
||||
expression: IS_INT('-1')
|
||||
result: true
|
||||
- name: "'1' is an int"
|
||||
expression: IS_INT('1')
|
||||
result: true
|
||||
- name: true is not an int
|
||||
expression: IS_INT(TRUE)
|
||||
result: false
|
||||
- name: "'abc' is not an int"
|
||||
expression: IS_INT('abc')
|
||||
result: false
|
||||
|
||||
- name: IS_STRING does not exists
|
||||
expression: IS_STRING('ABC')
|
||||
error: missingFunction
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
name: Context attributest test
|
||||
tests:
|
||||
- name: Access to required attribute
|
||||
expression: id
|
||||
eventOverrides:
|
||||
id: myId
|
||||
result: myId
|
||||
- name: Access to optional attribute
|
||||
expression: subject
|
||||
eventOverrides:
|
||||
subject: mySubject
|
||||
result: mySubject
|
||||
- name: Absent optional attribute
|
||||
expression: subject
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: localhost.localdomain
|
||||
type: myType
|
||||
result: ""
|
||||
error: missingAttribute
|
||||
- name: Access to optional boolean extension
|
||||
expression: mybool
|
||||
eventOverrides:
|
||||
mybool: true
|
||||
result: true
|
||||
- name: Access to optional integer extension
|
||||
expression: myint
|
||||
eventOverrides:
|
||||
myint: 10
|
||||
result: 10
|
||||
- name: Access to optional string extension
|
||||
expression: myext
|
||||
eventOverrides:
|
||||
myext: "my extension"
|
||||
result: "my extension"
|
||||
- name: URL type cohercion to string
|
||||
expression: source
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: "http://localhost/source"
|
||||
- name: Timestamp type cohercion to string
|
||||
expression: time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
time: 2018-04-26T14:48:09+02:00
|
||||
result: 2018-04-26T14:48:09+02:00
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
name: Exists expression
|
||||
tests:
|
||||
- name: required attributes always exist
|
||||
expression: EXISTS specversion AND EXISTS id AND EXISTS type AND EXISTS SOURCE
|
||||
result: true
|
||||
|
||||
- name: optional attribute available
|
||||
expression: EXISTS time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
time: 2018-04-26T14:48:09+02:00
|
||||
result: true
|
||||
- name: optional attribute absent
|
||||
expression: EXISTS time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: false
|
||||
- name: optional attribute absent (negated)
|
||||
expression: NOT EXISTS time
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: true
|
||||
|
||||
- name: optional extension available
|
||||
expression: EXISTS myext
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: my value
|
||||
result: true
|
||||
- name: optional extension absent
|
||||
expression: EXISTS myext
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: false
|
||||
- name: optional extension absent (negated)
|
||||
expression: NOT EXISTS myext
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: true
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
name: In expression
|
||||
tests:
|
||||
- name: int in int set
|
||||
expression: 123 IN (1, 2, 3, 12, 13, 23, 123)
|
||||
result: true
|
||||
- name: int not in int set
|
||||
expression: 123 NOT IN (1, 2, 3, 12, 13, 23, 123)
|
||||
result: false
|
||||
|
||||
- name: string in string set
|
||||
expression: "'abc' IN ('abc', \"bcd\")"
|
||||
result: true
|
||||
- name: string not in string set
|
||||
expression: "'aaa' IN ('abc', \"bcd\")"
|
||||
result: false
|
||||
|
||||
- name: bool in bool set
|
||||
expression: TRUE IN (TRUE, FALSE)
|
||||
result: true
|
||||
- name: bool not in bool set
|
||||
expression: TRUE IN (FALSE)
|
||||
result: false
|
||||
|
||||
- name: mix literals and identifiers (1)
|
||||
expression: source IN (myext, 'abc')
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: "http://localhost/source"
|
||||
result: true
|
||||
- name: mix literals and identifiers (2)
|
||||
expression: source IN (source)
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: "http://localhost/source"
|
||||
result: true
|
||||
- name: mix literals and identifiers (3)
|
||||
expression: "source IN (id, \"http://localhost/source\")"
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
myext: "http://localhost/source"
|
||||
result: true
|
||||
- name: mix literals and identifiers (4)
|
||||
expression: source IN (id, 'xyz')
|
||||
event:
|
||||
specversion: "1.0"
|
||||
id: myId
|
||||
source: "http://localhost/source"
|
||||
type: myType
|
||||
result: false
|
||||
|
||||
- name: type coercion with booleans (1)
|
||||
expression: "'true' IN (TRUE, 'false')"
|
||||
result: true
|
||||
- name: type coercion with booleans (2)
|
||||
expression: "'true' IN ('TRUE', 'false')"
|
||||
result: false
|
||||
- name: type coercion with booleans (3)
|
||||
expression: TRUE IN ('true', 'false')
|
||||
result: true
|
||||
- name: type coercion with booleans (4)
|
||||
expression: "'TRUE' IN (TRUE, 'false')"
|
||||
result: false
|
||||
|
||||
- name: type coercion with int (1)
|
||||
expression: "1 IN ('1', '2')"
|
||||
result: true
|
||||
- name: type coercion with int (2)
|
||||
expression: "'1' IN (1, 2)"
|
||||
result: true
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
name: Integer builtin functions
|
||||
tests:
|
||||
- name: ABS (1)
|
||||
expression: ABS(10)
|
||||
result: 10
|
||||
- name: ABS (2)
|
||||
expression: ABS(-10)
|
||||
result: 10
|
||||
- name: ABS (3)
|
||||
expression: ABS(0)
|
||||
result: 0
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
name: Like expression
|
||||
tests:
|
||||
- name: Exact match
|
||||
expression: "'abc' LIKE 'abc'"
|
||||
result: true
|
||||
- name: Exact match (negate)
|
||||
expression: "'abc' NOT LIKE 'abc'"
|
||||
result: false
|
||||
|
||||
- name: Percentage operator (1)
|
||||
expression: "'abc' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (2)
|
||||
expression: "'azbc' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (3)
|
||||
expression: "'azzzbzzzc' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (4)
|
||||
expression: "'a%b%c' LIKE 'a%b%c'"
|
||||
result: true
|
||||
- name: Percentage operator (5)
|
||||
expression: "'ac' LIKE 'abc'"
|
||||
result: false
|
||||
- name: Percentage operator (6)
|
||||
expression: "'' LIKE 'abc'"
|
||||
result: false
|
||||
|
||||
- name: Underscore operator (1)
|
||||
expression: "'abc' LIKE 'a_b_c'"
|
||||
result: false
|
||||
- name: Underscore operator (2)
|
||||
expression: "'a_b_c' LIKE 'a_b_c'"
|
||||
result: true
|
||||
- name: Underscore operator (3)
|
||||
expression: "'abzc' LIKE 'a_b_c'"
|
||||
result: false
|
||||
- name: Underscore operator (4)
|
||||
expression: "'azbc' LIKE 'a_b_c'"
|
||||
result: false
|
||||
- name: Underscore operator (5)
|
||||
expression: "'azbzc' LIKE 'a_b_c'"
|
||||
result: true
|
||||
|
||||
- name: Escaped underscore wildcards (1)
|
||||
expression: "'a_b_c' LIKE 'a\\_b\\_c'"
|
||||
result: true
|
||||
- name: Escaped underscore wildcards (2)
|
||||
expression: "'a_b_c' NOT LIKE 'a\\_b\\_c'"
|
||||
result: false
|
||||
- name: Escaped underscore wildcards (3)
|
||||
expression: "'azbzc' LIKE 'a\\_b\\_c'"
|
||||
result: false
|
||||
- name: Escaped underscore wildcards (4)
|
||||
expression: "'abc' LIKE 'a\\_b\\_c'"
|
||||
result: false
|
||||
|
||||
- name: Escaped percentage wildcards (1)
|
||||
expression: "'abc' LIKE 'a\\%b\\%c'"
|
||||
result: false
|
||||
- name: Escaped percentage wildcards (2)
|
||||
expression: "'a%b%c' LIKE 'a\\%b\\%c'"
|
||||
result: true
|
||||
- name: Escaped percentage wildcards (3)
|
||||
expression: "'azbzc' LIKE 'a\\%b\\%c'"
|
||||
result: false
|
||||
- name: Escaped percentage wildcards (4)
|
||||
expression: "'abc' LIKE 'a\\%b\\%c'"
|
||||
result: false
|
||||
|
||||
- name: With access to event attributes
|
||||
expression: "myext LIKE 'abc%123\\%456\\_d_f'"
|
||||
eventOverrides:
|
||||
myext: "abc123123%456_dzf"
|
||||
result: true
|
||||
- name: With access to event attributes (negated)
|
||||
expression: "myext NOT LIKE 'abc%123\\%456\\_d_f'"
|
||||
eventOverrides:
|
||||
myext: "abc123123%456_dzf"
|
||||
result: false
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
name: Literals
|
||||
tests:
|
||||
- name: TRUE literal
|
||||
expression: TRUE
|
||||
result: true
|
||||
- name: FALSE literal
|
||||
expression: FALSE
|
||||
result: false
|
||||
|
||||
- name: 0 literal
|
||||
expression: 0
|
||||
result: 0
|
||||
- name: 1 literal
|
||||
expression: 1
|
||||
result: 1
|
||||
|
||||
- name: String literal single quoted
|
||||
expression: "'abc'"
|
||||
result: abc
|
||||
- name: String literal double quoted
|
||||
expression: "\"abc\""
|
||||
result: abc
|
||||
|
||||
- name: String literal single quoted with case
|
||||
expression: "'aBc'"
|
||||
result: aBc
|
||||
- name: String literal double quoted with case
|
||||
expression: "\"AbC\""
|
||||
result: AbC
|
||||
|
||||
- name: Escaped string literal (1)
|
||||
expression: "'a\"b\\'c'"
|
||||
result: a"b'c
|
||||
- name: Escaped string literal (2)
|
||||
expression: "\"a'b\\\"c\""
|
||||
result: a'b"c
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
name: Negate operator
|
||||
tests:
|
||||
- name: Minus 10
|
||||
expression: -10
|
||||
result: -10
|
||||
- name: Minus minus 10
|
||||
expression: --10
|
||||
result: 10
|
||||
|
||||
- name: Minus 10 with casting
|
||||
expression: -'10'
|
||||
result: -10
|
||||
- name: Minus minus 10 with casting
|
||||
expression: --'10'
|
||||
result: 10
|
||||
|
||||
- name: Invalid boolean cast
|
||||
expression: -TRUE
|
||||
result: 0
|
||||
error: cast
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
name: Not operator
|
||||
tests:
|
||||
- name: Not true
|
||||
expression: NOT TRUE
|
||||
result: false
|
||||
- name: Not false
|
||||
expression: NOT FALSE
|
||||
result: true
|
||||
|
||||
- name: Not true with casting
|
||||
expression: NOT 'TRUE'
|
||||
result: false
|
||||
- name: Not false 10 with casting
|
||||
expression: NOT 'FALSE'
|
||||
result: true
|
||||
|
||||
- name: Invalid int cast
|
||||
expression: NOT 10
|
||||
result: true
|
||||
error: cast
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
name: Parsing errors
|
||||
tests:
|
||||
- name: No closed parenthesis
|
||||
expression: ABC(
|
||||
error: parse
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
name: Specification examples
|
||||
tests:
|
||||
- name: Case insensitive hops (1)
|
||||
expression: int(hop) < int(ttl) and int(hop) < 1000
|
||||
eventOverrides:
|
||||
hop: '5'
|
||||
ttl: '10'
|
||||
result: true
|
||||
- name: Case insensitive hops (2)
|
||||
expression: INT(hop) < INT(ttl) AND INT(hop) < 1000
|
||||
eventOverrides:
|
||||
hop: '5'
|
||||
ttl: '10'
|
||||
result: true
|
||||
- name: Case insensitive hops (3)
|
||||
expression: hop < ttl
|
||||
eventOverrides:
|
||||
hop: '5'
|
||||
ttl: '10'
|
||||
result: true
|
||||
|
||||
- name: Equals with casting (1)
|
||||
expression: sequence = 5
|
||||
eventOverrides:
|
||||
sequence: '5'
|
||||
result: true
|
||||
- name: Equals with casting (2)
|
||||
expression: sequence = 5
|
||||
eventOverrides:
|
||||
sequence: '6'
|
||||
result: false
|
||||
|
||||
- name: Logic expression (1)
|
||||
expression: firstname = 'Francesco' OR subject = 'Francesco'
|
||||
eventOverrides:
|
||||
subject: Francesco
|
||||
firstname: Doug
|
||||
result: true
|
||||
- name: Logic expression (2)
|
||||
expression: firstname = 'Francesco' OR subject = 'Francesco'
|
||||
eventOverrides:
|
||||
firstname: Francesco
|
||||
subject: Doug
|
||||
result: true
|
||||
- name: Logic expression (3)
|
||||
expression: (firstname = 'Francesco' AND lastname = 'Guardiani') OR subject = 'Francesco Guardiani'
|
||||
eventOverrides:
|
||||
subject: Doug
|
||||
firstname: Francesco
|
||||
lastname: Guardiani
|
||||
result: true
|
||||
- name: Logic expression (4)
|
||||
expression: (firstname = 'Francesco' AND lastname = 'Guardiani') OR subject = 'Francesco Guardiani'
|
||||
eventOverrides:
|
||||
subject: Francesco Guardiani
|
||||
firstname: Doug
|
||||
lastname: Davis
|
||||
result: true
|
||||
|
||||
- name: Subject exists
|
||||
expression: EXISTS subject
|
||||
eventOverrides:
|
||||
subject: Francesco Guardiani
|
||||
result: true
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
name: String builtin functions
|
||||
tests:
|
||||
- name: LENGTH (1)
|
||||
expression: "LENGTH('abc')"
|
||||
result: 3
|
||||
- name: LENGTH (2)
|
||||
expression: "LENGTH('')"
|
||||
result: 0
|
||||
- name: LENGTH (3)
|
||||
expression: "LENGTH('2')"
|
||||
result: 1
|
||||
- name: LENGTH (4)
|
||||
expression: "LENGTH(TRUE)"
|
||||
result: 4
|
||||
|
||||
- name: CONCAT (1)
|
||||
expression: "CONCAT('a', 'b', 'c')"
|
||||
result: abc
|
||||
- name: CONCAT (2)
|
||||
expression: "CONCAT()"
|
||||
result: ""
|
||||
- name: CONCAT (3)
|
||||
expression: "CONCAT('a')"
|
||||
result: "a"
|
||||
|
||||
- name: CONCAT_WS (1)
|
||||
expression: "CONCAT_WS(',', 'a', 'b', 'c')"
|
||||
result: a,b,c
|
||||
- name: CONCAT_WS (2)
|
||||
expression: "CONCAT_WS(',')"
|
||||
result: ""
|
||||
- name: CONCAT_WS (3)
|
||||
expression: "CONCAT_WS(',', 'a')"
|
||||
result: "a"
|
||||
- name: CONCAT_WS without arguments doesn't exist
|
||||
expression: CONCAT_WS()
|
||||
error: missingFunction
|
||||
|
||||
- name: LOWER (1)
|
||||
expression: "LOWER('ABC')"
|
||||
result: abc
|
||||
- name: LOWER (2)
|
||||
expression: "LOWER('AbC')"
|
||||
result: abc
|
||||
- name: LOWER (3)
|
||||
expression: "LOWER('abc')"
|
||||
result: abc
|
||||
|
||||
- name: UPPER (1)
|
||||
expression: "UPPER('ABC')"
|
||||
result: ABC
|
||||
- name: UPPER (2)
|
||||
expression: "UPPER('AbC')"
|
||||
result: ABC
|
||||
- name: UPPER (3)
|
||||
expression: "UPPER('abc')"
|
||||
result: ABC
|
||||
|
||||
- name: TRIM (1)
|
||||
expression: "TRIM(' a b c ')"
|
||||
result: "a b c"
|
||||
- name: TRIM (2)
|
||||
expression: "TRIM(' a b c')"
|
||||
result: "a b c"
|
||||
- name: TRIM (3)
|
||||
expression: "TRIM('a b c ')"
|
||||
result: "a b c"
|
||||
- name: TRIM (4)
|
||||
expression: "TRIM('a b c')"
|
||||
result: "a b c"
|
||||
|
||||
- name: LEFT (1)
|
||||
expression: LEFT('abc', 2)
|
||||
result: ab
|
||||
- name: LEFT (2)
|
||||
expression: LEFT('abc', 10)
|
||||
result: abc
|
||||
- name: LEFT (3)
|
||||
expression: LEFT('', 0)
|
||||
result: ""
|
||||
- name: LEFT (4)
|
||||
expression: LEFT('abc', -2)
|
||||
result: "abc"
|
||||
error: functionEvaluation
|
||||
|
||||
- name: RIGHT (1)
|
||||
expression: RIGHT('abc', 2)
|
||||
result: bc
|
||||
- name: RIGHT (2)
|
||||
expression: RIGHT('abc', 10)
|
||||
result: abc
|
||||
- name: RIGHT (3)
|
||||
expression: RIGHT('', 0)
|
||||
result: ""
|
||||
- name: RIGHT (4)
|
||||
expression: RIGHT('abc', -2)
|
||||
result: "abc"
|
||||
error: functionEvaluation
|
||||
|
||||
- name: SUBSTRING (1)
|
||||
expression: "SUBSTRING('abcdef', 1)"
|
||||
result: "abcdef"
|
||||
- name: SUBSTRING (2)
|
||||
expression: "SUBSTRING('abcdef', 2)"
|
||||
result: "bcdef"
|
||||
- name: SUBSTRING (3)
|
||||
expression: "SUBSTRING('Quadratically', 5)"
|
||||
result: "ratically"
|
||||
- name: SUBSTRING (4)
|
||||
expression: "SUBSTRING('Sakila', -3)"
|
||||
result: "ila"
|
||||
- name: SUBSTRING (5)
|
||||
expression: "SUBSTRING('abcdef', 1, 6)"
|
||||
result: "abcdef"
|
||||
- name: SUBSTRING (6)
|
||||
expression: "SUBSTRING('abcdef', 2, 4)"
|
||||
result: "bcde"
|
||||
- name: SUBSTRING (7)
|
||||
expression: "SUBSTRING('Sakila', -5, 3)"
|
||||
result: "aki"
|
||||
- name: SUBSTRING (8)
|
||||
expression: "SUBSTRING('Quadratically', 0)"
|
||||
result: ""
|
||||
- name: SUBSTRING (9)
|
||||
expression: "SUBSTRING('Quadratically', 0, 1)"
|
||||
result: ""
|
||||
- name: SUBSTRING (10)
|
||||
expression: "SUBSTRING('abcdef', 10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
- name: SUBSTRING (11)
|
||||
expression: "SUBSTRING('abcdef', -10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
- name: SUBSTRING (12)
|
||||
expression: "SUBSTRING('abcdef', 10, 10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
- name: SUBSTRING (13)
|
||||
expression: "SUBSTRING('abcdef', -10, 10)"
|
||||
result: ""
|
||||
error: functionEvaluation
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
name: Sub expressions
|
||||
tests:
|
||||
- name: Sub expression with literal
|
||||
expression: "(TRUE)"
|
||||
result: true
|
||||
|
||||
- name: Math (1)
|
||||
expression: "4 * (2 + 3)"
|
||||
result: 20
|
||||
- name: Math (2)
|
||||
expression: "(2 + 3) * 4"
|
||||
result: 20
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/cloudevents/sdk-go/sql/v2/parser"
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
"github.com/cloudevents/sdk-go/v2/binding/spec"
|
||||
"github.com/cloudevents/sdk-go/v2/event"
|
||||
"github.com/cloudevents/sdk-go/v2/test"
|
||||
)
|
||||
|
||||
var TCKFileNames = []string{
|
||||
"binary_math_operators",
|
||||
"binary_logical_operators",
|
||||
"binary_comparison_operators",
|
||||
"case_sensitivity",
|
||||
"casting_functions",
|
||||
"context_attributes_access",
|
||||
"exists_expression",
|
||||
"in_expression",
|
||||
"integer_builtin_functions",
|
||||
"like_expression",
|
||||
"literals",
|
||||
"negate_operator",
|
||||
"not_operator",
|
||||
"parse_errors",
|
||||
"spec_examples",
|
||||
"string_builtin_functions",
|
||||
"sub_expression",
|
||||
}
|
||||
|
||||
type ErrorType string
|
||||
|
||||
const (
|
||||
ParseError ErrorType = "parse"
|
||||
MathError ErrorType = "math"
|
||||
CastError ErrorType = "cast"
|
||||
MissingAttributeError ErrorType = "missingAttribute"
|
||||
MissingFunctionError ErrorType = "missingFunction"
|
||||
FunctionEvaluationError ErrorType = "functionEvaluation"
|
||||
)
|
||||
|
||||
type TckFile struct {
|
||||
Name string `json:"name"`
|
||||
Tests []TckTestCase `json:"tests"`
|
||||
}
|
||||
|
||||
type TckTestCase struct {
|
||||
Name string `json:"name"`
|
||||
Expression string `json:"expression"`
|
||||
|
||||
Result interface{} `json:"result"`
|
||||
Error ErrorType `json:"error"`
|
||||
|
||||
Event *cloudevents.Event `json:"event"`
|
||||
EventOverrides map[string]interface{} `json:"eventOverrides"`
|
||||
}
|
||||
|
||||
func (tc TckTestCase) InputEvent(t *testing.T) cloudevents.Event {
|
||||
var inputEvent cloudevents.Event
|
||||
if tc.Event != nil {
|
||||
inputEvent = *tc.Event
|
||||
} else {
|
||||
inputEvent = test.FullEvent()
|
||||
}
|
||||
|
||||
// Make sure the event is v1
|
||||
inputEvent.SetSpecVersion(event.CloudEventsVersionV1)
|
||||
|
||||
for k, v := range tc.EventOverrides {
|
||||
require.NoError(t, spec.V1.SetAttribute(inputEvent.Context, k, v))
|
||||
}
|
||||
|
||||
return inputEvent
|
||||
}
|
||||
|
||||
func (tc TckTestCase) ExpectedResult() interface{} {
|
||||
switch tc.Result.(type) {
|
||||
case int:
|
||||
return int32(tc.Result.(int))
|
||||
case float64:
|
||||
return int32(tc.Result.(float64))
|
||||
}
|
||||
return tc.Result
|
||||
}
|
||||
|
||||
func TestTCK(t *testing.T) {
|
||||
tckFiles := make([]TckFile, 0, len(TCKFileNames))
|
||||
|
||||
_, basePath, _, _ := runtime.Caller(0)
|
||||
basePath, _ = path.Split(basePath)
|
||||
|
||||
for _, testFile := range TCKFileNames {
|
||||
testFilePath := path.Join(basePath, "tck", testFile+".yaml")
|
||||
|
||||
t.Logf("Loading file %s", testFilePath)
|
||||
|
||||
file, err := os.Open(testFilePath)
|
||||
require.NoError(t, err)
|
||||
|
||||
fileBytes, err := ioutil.ReadAll(file)
|
||||
require.NoError(t, err)
|
||||
|
||||
tckFileModel := TckFile{}
|
||||
require.NoError(t, yaml.Unmarshal(fileBytes, &tckFileModel))
|
||||
|
||||
tckFiles = append(tckFiles, tckFileModel)
|
||||
}
|
||||
|
||||
for i, file := range tckFiles {
|
||||
i := i
|
||||
t.Run(file.Name, func(t *testing.T) {
|
||||
for j, testCase := range tckFiles[i].Tests {
|
||||
j := j
|
||||
t.Run(testCase.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCase := tckFiles[i].Tests[j]
|
||||
|
||||
t.Logf("Test expression: '%s'", testCase.Expression)
|
||||
|
||||
if testCase.Error == ParseError {
|
||||
_, err := parser.Parse(testCase.Expression)
|
||||
require.NotNil(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
expr, err := parser.Parse(testCase.Expression)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, expr)
|
||||
|
||||
inputEvent := testCase.InputEvent(t)
|
||||
result, err := expr.Evaluate(inputEvent)
|
||||
|
||||
if testCase.Error != "" {
|
||||
require.NotNil(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testCase.ExpectedResult(), result)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package v2
|
||||
|
||||
type Type uint8
|
||||
|
||||
const (
|
||||
StringType Type = iota
|
||||
IntegerType
|
||||
BooleanType
|
||||
AnyType
|
||||
)
|
||||
|
||||
func TypePtr(t Type) *Type {
|
||||
return &t
|
||||
}
|
||||
|
||||
func (t Type) IsSameType(val interface{}) bool {
|
||||
return TypeFromVal(val) == t
|
||||
}
|
||||
|
||||
func (t Type) String() string {
|
||||
switch t {
|
||||
case IntegerType:
|
||||
return "Integer"
|
||||
case BooleanType:
|
||||
return "Boolean"
|
||||
case StringType:
|
||||
return "String"
|
||||
}
|
||||
return "Any"
|
||||
}
|
||||
|
||||
func TypeFromVal(val interface{}) Type {
|
||||
switch val.(type) {
|
||||
case string:
|
||||
return StringType
|
||||
case int32:
|
||||
return IntegerType
|
||||
case bool:
|
||||
return BooleanType
|
||||
}
|
||||
return AnyType
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
cesql "github.com/cloudevents/sdk-go/sql/v2"
|
||||
)
|
||||
|
||||
func Cast(val interface{}, target cesql.Type) (interface{}, error) {
|
||||
if target.IsSameType(val) {
|
||||
return val, nil
|
||||
}
|
||||
switch target {
|
||||
case cesql.StringType:
|
||||
switch val.(type) {
|
||||
case int32:
|
||||
return strconv.Itoa(int(val.(int32))), nil
|
||||
case bool:
|
||||
if val.(bool) {
|
||||
return "true", nil
|
||||
} else {
|
||||
return "false", nil
|
||||
}
|
||||
}
|
||||
// Casting to string is always defined
|
||||
return fmt.Sprintf("%v", val), nil
|
||||
case cesql.IntegerType:
|
||||
switch val.(type) {
|
||||
case string:
|
||||
v, err := strconv.Atoi(val.(string))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("cannot cast from String to Integer: %w", err)
|
||||
}
|
||||
return int32(v), err
|
||||
}
|
||||
return 0, fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target)
|
||||
case cesql.BooleanType:
|
||||
switch val.(type) {
|
||||
case string:
|
||||
lowerCase := strings.ToLower(val.(string))
|
||||
if lowerCase == "true" {
|
||||
return true, nil
|
||||
} else if lowerCase == "false" {
|
||||
return false, nil
|
||||
}
|
||||
return false, fmt.Errorf("cannot cast String to Boolean, actual value: %v", val)
|
||||
}
|
||||
return false, fmt.Errorf("undefined cast from %v to %v", cesql.TypeFromVal(val), target)
|
||||
}
|
||||
|
||||
// AnyType doesn't need casting
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func CanCast(val interface{}, target cesql.Type) bool {
|
||||
_, err := Cast(val, target)
|
||||
return err == nil
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Copyright 2021 The CloudEvents Authors
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
cloudevents "github.com/cloudevents/sdk-go/v2"
|
||||
"github.com/cloudevents/sdk-go/v2/binding/spec"
|
||||
"github.com/cloudevents/sdk-go/v2/types"
|
||||
)
|
||||
|
||||
func GetAttribute(event cloudevents.Event, attributeName string) interface{} {
|
||||
var val interface{}
|
||||
|
||||
if a := spec.V1.Attribute(attributeName); a != nil { // Standard attribute
|
||||
val = a.Get(event.Context)
|
||||
} else {
|
||||
val = event.Extensions()[attributeName]
|
||||
}
|
||||
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type cohercion
|
||||
switch val.(type) {
|
||||
case bool, int32, string:
|
||||
return val
|
||||
case int8:
|
||||
return int32(val.(int8))
|
||||
case uint8:
|
||||
return int32(val.(uint8))
|
||||
case int16:
|
||||
return int32(val.(int16))
|
||||
case uint16:
|
||||
return int32(val.(uint16))
|
||||
case uint32:
|
||||
return int32(val.(uint32))
|
||||
case int64:
|
||||
return int32(val.(int64))
|
||||
case uint64:
|
||||
return int32(val.(uint64))
|
||||
case time.Time:
|
||||
return val.(time.Time).Format(time.RFC3339Nano)
|
||||
case []byte:
|
||||
return types.FormatBinary(val.([]byte))
|
||||
}
|
||||
return fmt.Sprintf("%v", val)
|
||||
}
|
||||
|
||||
func ContainsAttribute(event cloudevents.Event, attributeName string) bool {
|
||||
if attributeName == "specversion" || attributeName == "id" || attributeName == "source" || attributeName == "type" {
|
||||
return true
|
||||
}
|
||||
|
||||
if attr := spec.V1.Attribute(attributeName); attr != nil {
|
||||
return attr.Get(event.Context) != nil
|
||||
}
|
||||
|
||||
_, ok := event.Extensions()[attributeName]
|
||||
return ok
|
||||
}
|
||||
Loading…
Reference in New Issue