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

Implementing error types #117

Merged
merged 8 commits into from Apr 17, 2023
Merged

Conversation

rcypher-databricks
Copy link
Contributor

@rcypher-databricks rcypher-databricks commented Mar 24, 2023

Updated driver error handling to standardize on three error types: driver error (DBDriverError), request error (DBRequestError), and sql execution error (DBExecutionError). All three types have accessors for stack trace, correlation id, and connection id. DBExecutionError also has accessors for query Id and sql state.
The example in examples/error shows how to use errors.Is() and errors.As() to work with the error chain to determine error type and extract the state.

mattdeekay and others added 2 commits March 15, 2023 15:12
Signed-off-by: Matthew Kim <11141331+mattdeekay@users.noreply.github.com>
Refactored so that the interfaces for system, request, and execution errors are public in dbsql/errors.
Updated error implementations to work better with errors.Is() and errors.As().
Added sentinel values (SystemFault, RequestError, ExecutionError) in dbsql/errors to use with errors.Is()
Updated doc.go to include error information.
Updated errors examples.

Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
- updated rows package to use the new public error types
- refactored arrow/column based rows to put errors into a separate file
Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
@achettyiitr
Copy link

Any updates on this?

Copy link
Contributor

@andrefurlan-db andrefurlan-db left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have to be careful to not wrap context deadline exceeded with our errors

connection.go Outdated
@@ -217,16 +218,16 @@ func (c *conn) runQuery(ctx context.Context, query string, args []driver.NamedVa
cli_service.TOperationState_ERROR_STATE,
cli_service.TOperationState_TIMEDOUT_STATE:
logBadQueryState(log, statusResp)
return exStmtResp, statusResp, errors.New(statusResp.GetDisplayMessage())
return exStmtResp, statusResp, dbsqlerr.NewSystemFault(ctx, dbsqlerr.ErrInvalidOperationState, nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

request error?

Copy link
Contributor

@andrefurlan-db andrefurlan-db left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SystemFault has a different connotation than any driver error (such as not implemented). We need to either change this name to something like DriverError or really try to separate Databricks's system faults from the rest.

doc.go Outdated

DBSystemFault - A fault caused by Databricks services

DBRequestError - An error that is caused by an invalid request. Example: permission denied, or the user tries to access a warehouse that doesn’t exist
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some more examples would really help

@@ -195,21 +197,21 @@ func ParseDSN(dsn string) (UserConfig, error) {
}
parsedURL, err := url.Parse(fullDSN)
if err != nil {
return UserConfig{}, errors.Wrap(err, "invalid DSN: invalid format")
return UserConfig{}, dbsqlerr.NewRequestError(context.TODO(), dbsqlerr.ErrInvalidDSNFormat, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this makes sense? there is no request yet...but maybe any driver interaction is a "request"?

}
ucfg := UserConfig{}.WithDefaults()
ucfg.Protocol = parsedURL.Scheme
ucfg.Host = parsedURL.Hostname()
port, err := strconv.Atoi(parsedURL.Port())
if err != nil {
return UserConfig{}, errors.Wrap(err, "invalid DSN: invalid DSN port")
return UserConfig{}, dbsqlerr.NewRequestError(context.TODO(), dbsqlerr.ErrInvalidDSNPort, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we have a context for this function then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ParseDSN is called from databricksDriver.OpenConnector(dsn string) which doesn't take a context. We can't change OpenConnector() because it is part of the driver.DriverContext interface.

connector.go Outdated
@@ -35,7 +35,7 @@ func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {

tclient, err := client.InitThriftClient(c.cfg, c.client)
if err != nil {
return nil, dbsqlerr.WrapErr(err, "error initializing thrift client")
return nil, dbsqlerr.NewRequestError(ctx, dbsqlerr.ErrThriftClient, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

driver error

connector.go Outdated
@@ -66,7 +66,7 @@ func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
setStmt := fmt.Sprintf("SET `%s` = `%s`;", k, v)
_, err := conn.ExecContext(ctx, setStmt, []driver.NamedValue{})
if err != nil {
return nil, err
return nil, dbsqlerr.NewExecutionError(ctx, fmt.Sprintf("error setting session param: %s", setStmt), err, nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be just returning the error, no?

// Error messages
const (
// System Fault (driver errors, system failures)
ErrNotImplemented = "not implemented"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason why these are not public?

"github.com/joho/godotenv"
)

// NOTE: these tests print errors to the console and are for demonstration purposes, not unit test coverage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to make this file into a real example of how to use the error interfaces we are exposing. I am assuming that this file was not meant to be merged as is.

Made error messages public.
Renamed SystemFault to DriverError.
Fixed a few places where we were returning the wrong type of error.
Fixed a code path that would crash when the sentinel timed out.

Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
New example and fixed issues with errors.Is() and setting query id into context.

Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
Copy link
Contributor

@andrefurlan-db andrefurlan-db left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good to go now

@andrefurlan-db andrefurlan-db merged commit 36b12cd into databricks:main Apr 17, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants