Как поймать ошибки транзакции с гаечным ключом

#google-cloud-spanner #google-cloud-spanner-emulator

#google-облако-spanner #google-cloud-spanner-emulator

Вопрос:

В настоящее время я работаю над эмулятором spanner для своей локальной разработки и в конечном итоге буду использовать реальные экземпляры. Я пытаюсь запустить неверный SQL-запрос, ожидающий перехвата и выдачи сообщения об ошибке для пользователей.

Когда я запускаю приведенный ниже запрос с использованием cloud, я вижу HTTPError

gcloud spanner databases execute-sql --project=local-gcp-project testdb --instance=Emulator --sql='SELECT SingerId, AlbumId, AlbumTitle FROM Albums'

 (gcloud.spanner.databases.execute-sql) HTTPError 400: {"error":"Table not found: Albums [at 1:43]nSELECT SingerId, AlbumId, AlbumTitle FROM Albumsn^","code":3,"message":"Table not found: Albums [at 1:43]nSELECT SingerId, AlbumId, AlbumTitle FROM Albumsn^"}
 

Когда я использую клиентскую библиотеку python для выполнения одного и того же запроса, я не вижу никаких ошибок и вижу inside try , что они всегда печатаются.

 spanner_client = spanner.Client()
instance = spanner_client.instance("Emulator")
database = instance.database("testdb")

def execute_transaction(transaction):
   query = "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
   transaction.execute_sql(sql=query)
try:
  database.run_in_transaction(execute_transaction)
  print("inside try")
except GoogleAPICallError as e:
  print("inside e")
 

Есть идеи, чего мне может не хватать?

Ответ №1:

execute_sql возвращает a StreamedResultSet , который вычисляется лениво. Вы не увидите ошибку, пока не выполните итерацию по результату. Изменение вашего примера для чтения результирующего набора в список:

 from google.cloud import spanner_v1 as spanner
from google.api_core.exceptions import GoogleAPICallError

spanner_client = spanner.Client()
instance = spanner_client.instance("Emulator")
database = instance.database("testdb")

def execute_transaction(transaction):
    query = "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
    return list(transaction.execute_sql(sql=query))

try:
    database.run_in_transaction(execute_transaction)
    print("inside try")  # never gets here
except GoogleAPICallError as ex:
    print(ex)  # 400 Table not found: Albums...
 

Комментарии:

1. Спасибо, это было полезно. У меня есть куча SQL-запросов, которые необходимо выполнить. Похоже, мне нужно повторить результат для каждого из них. Это сработает для меня, но мне интересно, есть ли в базе данных параметр, который я могу изменить, чтобы изменить это поведение.

2. Нет, клиентские библиотеки Spanner возвращают итератор по дизайну. Если вы хотите получить все результаты, execute_transaction просто оберните их в a list , как в примере.