Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds syntactical support for CREATE FUNCTION #1180

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions partiql-ast/src/main/resources/partiql_ast.ion
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,33 @@ statement::[
definition: optional::table_definition,
},

// CREATE FUNCTION
create_function::{
specification: specification,
body: routine_body,
_: [
specification::{
name: '.identifier.qualified',
parameters: list::[parameter_declaration],
returns: returns,
characteristics: list::[routine_characteristic],
},
parameter_declaration::{
name: optional::'.identifier.symbol',
type: '.type'
},
// SQL:1999
// <returns clause> ::= RETURNS <returns data type> [ <result cast> ]
// <returns data type> ::= <data type> [ <locator indication> ]
// <result cast> ::= CAST FROM <result cast from type>
// <result cast from type> ::= <data type> [ <locator indication> ]
// TODO: Eventually add other grammatical rules here
returns::{
type: '.type'
}
]
},

// CREATE INDEX [<identifier>] ON <identifier> (<path> [, <path>]...)
create_index::{
index: optional::identifier,
Expand All @@ -133,6 +160,19 @@ statement::[
},
],

// SQL:1999
// <SQL control statement> ::=
// <call statement>
// | <return statement>
// <return statement> ::=
// RETURN <return value>
// <return value> ::=
// <value expression>
// | NULL
return::{
value: expr
},

// EXEC <symbol> [<expr>.*]
exec::{
procedure: string,
Expand All @@ -149,6 +189,26 @@ statement::[
},
],
},

_::[
// SQL:1999
// <routine body> ::=
// <SQL routine body> <-- nicknaming this `internal`
// | <external body reference> <-- nicknaming this `external`
routine_body::[
// SQL:1999
// <SQL routine body> (nicknamed `internal`) ::= <SQL procedure statement>
// Note: Semantic pass should ensure the statement is a procedure statement.
internal::{
procedure_statement: statement
}
],
routine_characteristic::[
specific::{
name: '.identifier.qualified'
}
]
]
]

// PartiQL Type AST nodes
Expand Down
145 changes: 145 additions & 0 deletions partiql-parser/src/main/antlr/PartiQL.g4
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,153 @@ statement
| dml COLON_SEMI? EOF # QueryDml
| ddl COLON_SEMI? EOF # QueryDdl
| execCommand COLON_SEMI? EOF # QueryExec
| sqlInvokedRoutine # CreateRoutineStatement
;

// SQL:1999
// <SQL-invoked routine> ::= <schema routine>
sqlInvokedRoutine
: schemaRoutine
;

// SQL:1999
// <schema routine> ::=
// <schema procedure>
// | <schema function>
schemaRoutine
: schemaFunction
;

// SQL:1999
// <schema function> ::=
// CREATE <SQL-invoked function>
schemaFunction
: CREATE sqlInvokedFunction
;

// SQL:1999
// <SQL-invoked function> ::=
// { <function specification> | <method specification designator> }
// <routine body>
sqlInvokedFunction
:
(
functionSpecification
) routineBody
;

// SQL:1999
// <function specification> ::=
// FUNCTION <schema qualified routine name>
// <SQL parameter declaration list>
// <returns clause>
// <routine characteristics>
// [ <dispatch clause> ]
functionSpecification
: FUNCTION name=symbolPrimitive // FIXME: Should be schemaQualifiedRoutineName
sqlParameterDeclarationList
returnsClause
routineCharacteristic*
;

// SQL:1999
// <routine characteristic> ::=
// SPECIFIC <specific name>
// | and many more...
routineCharacteristic
: SPECIFIC specificName
;

// SQL:1999
// <specific name> ::= <schema qualified name>
specificName
: name=symbolPrimitive // FIXME: should be ```schemaQualifiedName```
;

// SQL:1999
// <returns clause> ::= RETURNS <returns data type> [ <result cast> ]
returnsClause
: RETURNS returnsDataType
;

// SQL:1999
// <returns data type> ::= <data type> [ <locator indication> ]
returnsDataType
: type
;

// SQL:1999
// <routine body> ::=
// <SQL routine body>
// | <external body reference>
routineBody
: sqlRoutineBody
;

// SQL:1999
// <SQL parameter declaration list> ::=
// <left paren>
// [ <SQL parameter declaration> [ { <comma> <SQL parameter declaration> }... ] ]
// <right paren>
sqlParameterDeclarationList
: PAREN_LEFT (sqlParameterDeclaration (COMMA sqlParameterDeclaration)* )? PAREN_RIGHT
;

// SQL:1999
// <SQL parameter declaration> ::=
// [ <parameter mode> ] [ <SQL parameter name> ]
// <parameter type>
// [ RESULT ]
sqlParameterDeclaration
: sqlParameterName? parameterType
;

// SQL:1999
// <SQL parameter name> ::= <identifier>
sqlParameterName
: symbolPrimitive
;

// SQL:1999
// <parameter type> ::=
// <data type> [ <locator indication> ]
parameterType
: type
;

// SQL:1999
// <SQL routine body> ::= <SQL procedure statement>
sqlRoutineBody: sqlProcedureStatement;

// SQL:1999
// <SQL procedure statement> ::= <SQL executable statement>
sqlProcedureStatement: sqlExecutableStatement;

// SQL:1999
// <SQL executable statement> ::=
// <SQL control statement>
// | many more alternatives...
sqlExecutableStatement
: sqlControlStatement
;

// SQL:1999
// <SQL control statement> ::=
// <call statement>
// | <return statement>
sqlControlStatement
: returnStatement
;

// SQL:1999
// <return statement> ::=
// RETURN <return value>
// <return value> ::=
// <value expression>
// | NULL
returnStatement
: RETURN expr;

/**
*
* COMMON STRUCTURES
Expand Down
4 changes: 4 additions & 0 deletions partiql-parser/src/main/antlr/PartiQLTokens.g4
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ FOREIGN: 'FOREIGN';
FOUND: 'FOUND';
FROM: 'FROM';
FULL: 'FULL';
FUNCTION: 'FUNCTION';
GET: 'GET';
GLOBAL: 'GLOBAL';
GO: 'GO';
Expand Down Expand Up @@ -197,6 +198,8 @@ REFERENCES: 'REFERENCES';
RELATIVE: 'RELATIVE';
REPLACE: 'REPLACE';
RESTRICT: 'RESTRICT';
RETURN: 'RETURN';
RETURNS: 'RETURNS';
REVOKE: 'REVOKE';
RIGHT: 'RIGHT';
ROLLBACK: 'ROLLBACK';
Expand All @@ -213,6 +216,7 @@ SIZE: 'SIZE';
SMALLINT: 'SMALLINT';
SOME: 'SOME';
SPACE: 'SPACE';
SPECIFIC: 'SPECIFIC';
SQL: 'SQL';
SQLCODE: 'SQLCODE';
SQLERROR: 'SQLERROR';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,82 @@ internal class PartiQLParserDefault : PartiQLParser {
statementExec(procedure, args)
}

// FUNCTION

override fun visitSqlInvokedRoutine(ctx: org.partiql.parser.antlr.PartiQLParser.SqlInvokedRoutineContext?): AstNode {
return super.visitSqlInvokedRoutine(ctx)
}

override fun visitSchemaRoutine(ctx: org.partiql.parser.antlr.PartiQLParser.SchemaRoutineContext?): AstNode {
return super.visitSchemaRoutine(ctx)
}

override fun visitSchemaFunction(ctx: org.partiql.parser.antlr.PartiQLParser.SchemaFunctionContext?): AstNode {
return super.visitSchemaFunction(ctx)
}

override fun visitSqlInvokedFunction(ctx: org.partiql.parser.antlr.PartiQLParser.SqlInvokedFunctionContext) = translate(ctx) {
val specification = visitFunctionSpecification(ctx.functionSpecification())
val body = visitRoutineBody(ctx.routineBody())
statementDDLCreateFunction(specification, body)
}

override fun visitFunctionSpecification(ctx: org.partiql.parser.antlr.PartiQLParser.FunctionSpecificationContext) = translate(ctx) {
val root = visitSymbolPrimitive(ctx.name)
val name = identifierQualified(root, emptyList())
val parameters = ctx.sqlParameterDeclarationList().sqlParameterDeclaration().map { decl ->
visitSqlParameterDeclaration(decl)
}
val returns = visitReturnsClause(ctx.returnsClause())
val characteristics = ctx.routineCharacteristic().map { characteristic ->
visitRoutineCharacteristic(characteristic)
}
statementDDLCreateFunctionSpecification(name, parameters, returns, characteristics)
}

override fun visitSqlParameterDeclaration(ctx: org.partiql.parser.antlr.PartiQLParser.SqlParameterDeclarationContext) = translate(ctx) {
val name = ctx.sqlParameterName()?.let { visitSymbolPrimitive(it.symbolPrimitive()) }
val type = visit(ctx.parameterType().type()) as Type
statementDDLCreateFunctionParameterDeclaration(name, type)
}

override fun visitReturnsClause(ctx: org.partiql.parser.antlr.PartiQLParser.ReturnsClauseContext) = translate(ctx) {
val type = visit(ctx.returnsDataType().type()) as Type
statementDDLCreateFunctionReturns(type)
}

override fun visitRoutineCharacteristic(ctx: org.partiql.parser.antlr.PartiQLParser.RoutineCharacteristicContext) = translate(ctx) {
val name = visitSymbolPrimitive(ctx.specificName().name)
val specificName = identifierQualified(name, emptyList())
statementRoutineCharacteristicSpecific(specificName)
}

override fun visitReturnStatement(ctx: org.partiql.parser.antlr.PartiQLParser.ReturnStatementContext) = translate(ctx) {
val expr = visitExpr(ctx.expr())
statementReturn(expr)
}

override fun visitSqlProcedureStatement(ctx: org.partiql.parser.antlr.PartiQLParser.SqlProcedureStatementContext?): AstNode {
return super.visitSqlProcedureStatement(ctx)
}

override fun visitSqlExecutableStatement(ctx: org.partiql.parser.antlr.PartiQLParser.SqlExecutableStatementContext?): AstNode {
return super.visitSqlExecutableStatement(ctx)
}

override fun visitRoutineBody(ctx: org.partiql.parser.antlr.PartiQLParser.RoutineBodyContext) = translate(ctx) {
visitSqlRoutineBody(ctx.sqlRoutineBody())
}

override fun visitSqlRoutineBody(ctx: org.partiql.parser.antlr.PartiQLParser.SqlRoutineBodyContext) = translate(ctx) {
val stmt = visitSqlProcedureStatement(ctx.sqlProcedureStatement()) as Statement
statementRoutineBodyInternal(stmt)
}

override fun visitSqlControlStatement(ctx: org.partiql.parser.antlr.PartiQLParser.SqlControlStatementContext?): AstNode {
return super.visitSqlControlStatement(ctx)
}

/**
*
* DATA MANIPULATION LANGUAGE (DML)
Expand Down Expand Up @@ -1835,6 +1911,7 @@ internal class PartiQLParserDefault : PartiQLParser {
val n = ctx.arg0?.text?.toInt()
when (ctx.datatype.type) {
GeneratedParser.FLOAT -> when (n) {
null -> typeFloat64()
32 -> typeFloat32()
64 -> typeFloat64()
else -> throw error(ctx.datatype, "Invalid FLOAT precision. Expected 32 or 64")
Expand Down
Loading
Loading