Skip to content

Commit

Permalink
Expression language (#363)
Browse files Browse the repository at this point in the history
* Configured the sql package

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Bootstrap implementation

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Literal done

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* More progress

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Progress

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Sync contract

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fix type cohercion for event type system

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* In expression + sync grammar

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Implemented binary expressions

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Implemented Like expression

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Big refactor

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* More testing
Fix math

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Implemented all the functions!

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Refactored logical expressions implementation
More testing

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* More coverage and tests

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fixed ConcatFunction and added ConcatWSFunction

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fixed IN type casting

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added ABS function

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fix SUBSTRING implementation

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* More nits

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* WIP Javadoc-ing

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fix division by 0

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Bootstrapped TCK

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added comparison operators to tck

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added logical operators, case sensitivity and casting functions

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Copied all the tests to the tck

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Removed Java tests now covered by the TCK

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added integer builtin test case

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Added fail fast evaluation mode

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* More changes
More Javadoc

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Typo

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Fix bad javadoc

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Another CONCAT_WS test case

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>

* Import yaml just for testing

Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
  • Loading branch information
slinkydeveloper committed Apr 28, 2021
1 parent 30fd676 commit 2730ae4
Show file tree
Hide file tree
Showing 90 changed files with 4,284 additions and 0 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<module>http/restful-ws</module>
<module>kafka</module>
<module>spring</module>
<module>sql</module>
</modules>

<properties>
Expand Down
93 changes: 93 additions & 0 deletions sql/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloudevents-parent</artifactId>
<groupId>io.cloudevents</groupId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloudevents-sql</artifactId>

<properties>
<module-name>io.cloudevents.sql</module-name>
<antlr.version>4.9.2</antlr.version>
</properties>

<dependencies>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${antlr.version}</version>
</dependency>

<!-- Test deps -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-json-jackson</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cloudevents</groupId>
<artifactId>cloudevents-core</artifactId>
<classifier>tests</classifier>
<type>test-jar</type>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>${antlr.version}</version>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
<configuration>
<visitor>true</visitor>
<listener>true</listener> <!-- TODO do we need the listener? -->
</configuration>
</plugin>
</plugins>
</build>

</project>
79 changes: 79 additions & 0 deletions sql/src/main/antlr4/imports/CESQLLexer.g4
Original file line number Diff line number Diff line change
@@ -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_]*;
62 changes: 62 additions & 0 deletions sql/src/main/antlr4/io/cloudevents/sql/generated/CESQLParser.g4
Original file line number Diff line number Diff line change
@@ -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
;
36 changes: 36 additions & 0 deletions sql/src/main/java/io/cloudevents/sql/EvaluationContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.cloudevents.sql;

import org.antlr.v4.runtime.misc.Interval;

/**
* This class wraps some elements of the evaluation context,
* required to throw {@link EvaluationException} when an error occurs while evaluating a function.
*/
public interface EvaluationContext {

/**
* @return the interval of the original expression string.
*/
Interval expressionInterval();

/**
* @return the text of the original expression string.
*/
String expressionText();

/**
* Append a new exception to the evaluation context.
* This exception will be propagated back in the evaluation result.
*
* @param exception exception to append
*/
void appendException(EvaluationException exception);

/**
* Append a new exception to the evaluation context.
* This exception will be propagated back in the evaluation result.
*
* @param exceptionFactory exception factory, which will automatically include expression interval and text
*/
void appendException(EvaluationException.EvaluationExceptionFactory exceptionFactory);
}
Loading

0 comments on commit 2730ae4

Please sign in to comment.