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
Conversation
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>
e447bf0
to
fb50b06
Compare
Signed-off-by: Raymond Cypher <raymond.cypher@databricks.com>
Any updates on 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.
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) |
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.
request error?
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.
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 |
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.
some more examples would really help
internal/config/config.go
Outdated
@@ -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) |
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.
does this makes sense? there is no request yet...but maybe any driver interaction is a "request"?
internal/config/config.go
Outdated
} | ||
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) |
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.
should we have a context for this function then?
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.
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) |
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.
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) |
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.
this should be just returning the error, no?
internal/errors/err.go
Outdated
// Error messages | ||
const ( | ||
// System Fault (driver errors, system failures) | ||
ErrNotImplemented = "not implemented" |
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.
any reason why these are not public?
examples/error/main.go
Outdated
"github.com/joho/godotenv" | ||
) | ||
|
||
// NOTE: these tests print errors to the console and are for demonstration purposes, not unit test coverage |
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 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>
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 think this is good to go now
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.