-
Notifications
You must be signed in to change notification settings - Fork 62
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
Initializes PartiQL's error reporting mechanism #1615
Conversation
196565b
to
c51d9c7
Compare
@@ -24,7 +24,7 @@ import org.partiql.spi.catalog.Session | |||
*/ | |||
public interface PartiQLEngine { | |||
|
|||
public fun prepare(plan: Plan, mode: Mode, session: Session): PartiQLStatement | |||
public fun prepare(plan: Plan, session: Session, config: CompilerConfig): PartiQLStatement |
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.
I suggest changing the "Config" to something more like Context which may or may not be part of the session, but perhaps these are slightly different?
The Config reads like what should be part of a PartiQLEngine/PartiQLParser/PartiQLPlanner builders. Why not have PartiQLParser.builder().addListener(...)
because the "config" is what the constructor arguments are for.
I am curious the use-case of having a changing config for each invocation, and where a session context wouldn't achieve this.
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.
Having the error listener as part of a context/config allows for end-users to create singleton planners (if they want to). They're given the freedom to always pass the same object, or to pass in new error listeners.
That being said, I'm up for adding it to the session context -- but I wasn't entirely sure the right place to put it.
/** | ||
* Represents the configuration for the {@link PartiQLParser}. | ||
* | ||
* @see PartiQLParser | ||
* @see ParserConfigBuilder | ||
*/ | ||
public interface ParserConfig { | ||
/** | ||
* @return The error listener to be used by the compiler. | ||
*/ | ||
@NotNull | ||
PErrorListener getErrorListener(); | ||
} |
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 are some reasons not to add listeners via constructors (or even mutable class methods) like ANTLR has. These configs add a several more classes to juggle and thread through all calls, which seems like additional complexity but I may be missing how these are more useful than just adding listeners via the builders.
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.
See #1615 (comment).
partiql-planner/src/main/kotlin/org/partiql/planner/internal/problems/AlwaysMissing.kt
Outdated
Show resolved
Hide resolved
@NotNull | ||
public static Classification COMPILATION() { | ||
return new Classification(COMPILATION); | ||
} | ||
|
||
/** | ||
* TODO | ||
*/ | ||
public static final int EXECUTION = 4; |
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 are some examples of compilation vs execution errors?
In a recent message we were talking about how lazy datums hide execution problems. I'm not sure I understand how we might get an execution PError rather than something akin to a "runtime exception" when materializing a lazy datum.
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.
Perhaps some driver in partiql-lang would take a listener an it might emit execution errors? I somewhat think partiql-eval should have an evaluator driver that can emit them. By driver, I just mean something that materializes Datums. So a customer may choose to use the lazy datum, or just invoke an eval() which actually performs the work and accepts a listener. Does that make sense?
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 are some examples of compilation vs execution errors?
Compilation errors might happen if the plan is referencing a custom physical operator that doesn't exist, or if a feature is not supported for execution (yet). It describes taking the process of taking the input plan and outputting an executable. There may be many types of errors at this stage.
Execution errors may be emitted during actual execution, such as data exceptions. I actually discuss this briefly in the usage guide, but the idea is that all components will standardize the fact the the only JVM exception that these components will see is the PErrorListenerException
. Though, for exceptions that arise during the execution of the prepared statement, I detailed an EvaluationException
that essentially wraps a PError
.
partiql-spi/src/main/java/org/partiql/spi/errors/Classification.java
Outdated
Show resolved
Hide resolved
Adds multiple error reporting options to the CLI Adds usage guide
Renames Error to Problem Internalizes the construction of problems Creates a PEnum
Adds Javadocs to PErrorKind and Severity
cb248c2
to
a993ec5
Compare
partiql-eval/src/main/java/org/partiql/eval/CompilerContext.java
Outdated
Show resolved
Hide resolved
partiql-planner/src/main/kotlin/org/partiql/planner/PartiQLPlannerPass.kt
Outdated
Show resolved
Hide resolved
Creates a shared Context in SPI
Updates usage guide
public fun prepare(plan: Plan, session: Session, ctx: Context): PartiQLStatement { | ||
return prepare(plan, session, ctx, Mode.STRICT) | ||
} | ||
|
||
public fun prepare(plan: Plan, session: Session, mode: Mode): PartiQLStatement { | ||
return prepare(plan, session, Context.standard(), mode) | ||
} |
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.
no default mode and the ctx with/without are the overloads so something like
public fun prepare(plan: Plan, session: Session, ctx: Context): PartiQLStatement { | |
return prepare(plan, session, ctx, Mode.STRICT) | |
} | |
public fun prepare(plan: Plan, session: Session, mode: Mode): PartiQLStatement { | |
return prepare(plan, session, Context.standard(), mode) | |
} | |
public fun prepare(plan: Plan, mode: Mode): PartiQLStatement { | |
return prepare(plan, mode, Context.NONE) | |
} | |
public fun prepare(plan: Plan, mode: Mode, ctx: Context): PartiQLStatement |
I can follow up since this will go on the java PartiQLCompiler interface so no more kt engine thing.
@NotNull | ||
default PErrorListener getErrorListener() { | ||
return PErrorListener.abortOnError(); | ||
} |
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.
I'm not sure we want to instantiate a new error listener every time, this is somewhat like the argument changing everytime. We can have a TODO to make AbortOnError a static variable
Relevant Issues
Description
PError
,PErrorListener
, andPErrorListenerException
.PEnum
,Severity
, andClassification
.Error
andProblem
APIs.Follow-ups
PartiQLSyntaxException
-- which was made internal by this PR. But we no longer need to convert to a syntax exception and then to an error code.License Information
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.