Description
If I have a table that already exists and try to create the same table, this package errors but its error code is None yet its message is Duplicate name in schema:
.
Reproduction
from google.cloud import spanner_v1 as spanner
def main():
db = spanner.Client().instance('django-tests').database('db1')
lro = db.update_ddl(['CREATE TABLE foo (id INT64) PRIMARY KEY(id)'])
try:
result = lro.result()
except Exception as e:
print('\033[31mCode: %s gRPC_StatusCode: %s Message: %s\033[00m' %
(e.code, e.grpc_status_code, e.message))
raise e
else:
print(result)
if __name__ == '__main__':
main()
which unfortunately prints out
Code: None gRPC_StatusCode: None Message: Duplicate name in schema: foo.
Traceback (most recent call last):
File "duplicate_table_v1.py", line 18, in <module>
main()
File "duplicate_table_v1.py", line 12, in main
raise e
File "duplicate_table_v1.py", line 8, in main
result = lro.result()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/google/api_core/future/polling.py", line 127, in result
raise self._exception
google.api_core.exceptions.GoogleAPICallError: None Duplicate name in schema: foo.
This bug presents an inconsistency in the error handling because we get an error with a None
status code and None
gRPC status code, yet it has a message.
Comparison with Go
I can confirm that Cloud Spanner actually sends back the status code because the Go result actually has the status code, with this reproduction and by investigation the responses sent by the Spanner server
package main
import (
"context"
dbadmin "cloud.google.com/go/spanner/admin/database/apiv1"
dbspb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
)
func main() {
ctx := context.Background()
adminClient, err := dbadmin.NewDatabaseAdminClient(ctx)
if err != nil {
panic(err)
}
ddlReq := &dbspb.UpdateDatabaseDdlRequest{
Database: "projects/orijtech-161805/instances/django-tests/databases/db1",
Statements: []string{
"CREATE TABLE foo (id INT64) PRIMARY KEY(id)",
},
}
lro, err := adminClient.UpdateDatabaseDdl(ctx, ddlReq)
if err != nil {
panic(err)
}
if err := lro.Wait(ctx); err != nil {
panic(err)
}
}
and prints out
Sleeping for 947.779411ms
panic: rpc error: code = FailedPrecondition desc = Duplicate name in schema: foo.
goroutine 1 [running]:
main.main()
/Users/emmanuelodeke/Desktop/spanner-orm-trials/duplicate_table.go:27 +0x1db
exit status 2
Postulation
I think that the result of waiting on the long running operation isn't being properly used to retrieve the status code.
/cc @larkee @skuruppu, and for an FYI @bvandiver @timgraham