-
Notifications
You must be signed in to change notification settings - Fork 63
Add stored procedure calls with unnamed args #345
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #345 +/- ##
============================================
- Coverage 82.37% 82.04% -0.33%
- Complexity 1233 1244 +11
============================================
Files 157 159 +2
Lines 9366 9514 +148
Branches 1526 1546 +20
============================================
+ Hits 7715 7806 +91
- Misses 1192 1244 +52
- Partials 459 464 +5
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
|
||
return PartiqlAst.build { | ||
when (node) { | ||
is Exec -> exec(node.procedureName.name, node.args.map { it.toAstExpr() }, metas) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
procedureName.meta
is not kept in PartiqlAst.Statement
? Not to say it's important but just want to confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That particular meta
may not be too important, but we should be copying metas wherever possible. I will add that in the next commit.
I noticed there are quite a few other metas that aren't copied when converting ExprNode
<-> PartiqlAst
, so I created an issue (#353) to track.
@@ -2214,9 +2242,23 @@ class SqlParser(private val ion: IonSystem) : Parser { | |||
return ParseNode(ARG_LIST, null, items, rem) | |||
} | |||
|
|||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are other tokens that should only exist at top level right? Why is EXEC
different and requires a separate check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other tokens that should only exist at the top level (i.e. DML and DDL ops) weren't properly checked in the parser (created an issue #354 to add these checks in the future). I will rename the checkForUnexpectedExec()
to something more general for all tokens that should only exist in the top level.
Property.TOKEN_VALUE to ion.newSymbol("exec"))) | ||
|
||
@Test | ||
fun execAtUnexpectedLocationInExpression() = checkInputThrowingParserException( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen for SELECT * FROM EXEC
or SELECT * FROM exec
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently for both of those queries, the PARSE_EXEC_AT_UNEXPECTED_LOCATION
will be thrown. Perhaps I can make it more general for other tokens that should only be at the top-level.
|
||
/** | ||
* Invokes the stored procedure. Proper arity is checked by the [EvaluatingCompiler], but argument type checking | ||
* is left to the implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not related to this change but wonder if there could be some utility for user to easily build their type check. Would be useful in many places, not limited to stored procedure. BTW I heard ExprValue
is going to be deprecated? Maybe it's better to consider utility after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have some future plans to add a utility to help type-check stored procedures and user-defined functions.
ExprValue
will likely be deprecated sometime in the future, so the utility will probably be implemented with its replacement.
@@ -432,6 +445,16 @@ enum class ErrorCode(private val category: ErrorCategory, | |||
"got: ${errorContext?.get(Property.ACTUAL_ARGUMENT_TYPES) ?: UNKNOWN}" | |||
}, | |||
|
|||
EVALUATOR_INCORRECT_TYPE_OF_ARGUMENTS_TO_PROCEDURE_CALL( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to comment, type check is done in procedure implementation, so usage of this error code depends on user's best intention. As mentioned in the other comment, this could be improved by taking over type check or providing utility to help user defining their own type check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the other reply, we do have plans to add a type-checking utility for sprocs and udfs, so once that's added, throwing of this error should be handled by that utility.
internal = false) | ||
|
||
// Check arity | ||
if (args.size !in procedure.signature.arity) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just found something weird regarding IntRange
: IntRange(2,1)
is valid, no exception, but internally it assumes start <= end (link). 1 in IntRange(1,2)=true
but 1 in IntRange(2,1)=false
. Not to say we should do anything about it but maybe good to know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm interesting. I don't think that internally IntRange
assumes start <= end. The Kotlin 1.3 jar even defines an EMPTY
range as IntRange(1, 0)
. It seems in
(i.e. contains
) only returns true if and only if start <= value && value <= last
, so the behavior makes some sense.
This leads me to think that nothing should be done unless we decide not to use IntRange
.
Adds the ability to create custom stored procedures and call them with the
EXEC
clause, following the description given in this issue.Also provides a simple custom stored procedure example.
Previously approved PRs part of this PR:
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.