google-cloud-spanner 3.42.0__tar.gz → 3.43.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. {google-cloud-spanner-3.42.0/google_cloud_spanner.egg-info → google-cloud-spanner-3.43.0}/PKG-INFO +1 -1
  2. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/gapic_version.py +1 -1
  3. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/gapic_version.py +1 -1
  4. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/_helpers.py +2 -2
  5. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/client_side_statement_executor.py +2 -0
  6. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/client_side_statement_parser.py +7 -0
  7. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/connection.py +73 -3
  8. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/cursor.py +24 -5
  9. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/parse_utils.py +3 -1
  10. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/parsed_statement.py +6 -0
  11. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/batch.py +9 -1
  12. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/database.py +62 -12
  13. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/gapic_version.py +1 -1
  14. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/session.py +4 -0
  15. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/snapshot.py +0 -4
  16. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/table.py +55 -13
  17. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/transaction.py +26 -7
  18. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0/google_cloud_spanner.egg-info}/PKG-INFO +1 -1
  19. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_database_api.py +40 -0
  20. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_dbapi.py +22 -0
  21. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_session_api.py +48 -2
  22. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_table_api.py +1 -1
  23. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_connection.py +93 -5
  24. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_cursor.py +11 -3
  25. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_parse_utils.py +14 -0
  26. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_batch.py +45 -9
  27. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_database.py +12 -5
  28. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_snapshot.py +0 -22
  29. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_spanner.py +14 -0
  30. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_table.py +13 -6
  31. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_transaction.py +53 -30
  32. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/LICENSE +0 -0
  33. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/MANIFEST.in +0 -0
  34. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/README.rst +0 -0
  35. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner.py +0 -0
  36. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/__init__.py +0 -0
  37. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/gapic_metadata.json +0 -0
  38. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/py.typed +0 -0
  39. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/__init__.py +0 -0
  40. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/__init__.py +0 -0
  41. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/async_client.py +0 -0
  42. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/client.py +0 -0
  43. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/pagers.py +0 -0
  44. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/__init__.py +0 -0
  45. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/base.py +0 -0
  46. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc.py +0 -0
  47. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/grpc_asyncio.py +0 -0
  48. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/services/database_admin/transports/rest.py +0 -0
  49. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/types/__init__.py +0 -0
  50. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/types/backup.py +0 -0
  51. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/types/common.py +0 -0
  52. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_database_v1/types/spanner_database_admin.py +0 -0
  53. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/__init__.py +0 -0
  54. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/gapic_metadata.json +0 -0
  55. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/py.typed +0 -0
  56. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/__init__.py +0 -0
  57. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/__init__.py +0 -0
  58. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/async_client.py +0 -0
  59. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/client.py +0 -0
  60. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/pagers.py +0 -0
  61. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/__init__.py +0 -0
  62. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/base.py +0 -0
  63. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc.py +0 -0
  64. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/grpc_asyncio.py +0 -0
  65. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/services/instance_admin/transports/rest.py +0 -0
  66. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/types/__init__.py +0 -0
  67. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/types/common.py +0 -0
  68. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_admin_instance_v1/types/spanner_instance_admin.py +0 -0
  69. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/__init__.py +0 -0
  70. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/batch_dml_executor.py +0 -0
  71. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/checksum.py +0 -0
  72. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/exceptions.py +0 -0
  73. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/parser.py +0 -0
  74. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/partition_helper.py +0 -0
  75. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/transaction_helper.py +0 -0
  76. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/types.py +0 -0
  77. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/utils.py +0 -0
  78. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_dbapi/version.py +0 -0
  79. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/__init__.py +0 -0
  80. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/_helpers.py +0 -0
  81. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/_opentelemetry_tracing.py +0 -0
  82. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/backup.py +0 -0
  83. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/client.py +0 -0
  84. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/data_types.py +0 -0
  85. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/gapic_metadata.json +0 -0
  86. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/instance.py +0 -0
  87. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/keyset.py +0 -0
  88. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/merged_result_set.py +0 -0
  89. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/param_types.py +0 -0
  90. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/pool.py +0 -0
  91. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/py.typed +0 -0
  92. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/__init__.py +0 -0
  93. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/__init__.py +0 -0
  94. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/async_client.py +0 -0
  95. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/client.py +0 -0
  96. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/pagers.py +0 -0
  97. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/transports/__init__.py +0 -0
  98. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/transports/base.py +0 -0
  99. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/transports/grpc.py +0 -0
  100. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/transports/grpc_asyncio.py +0 -0
  101. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/services/spanner/transports/rest.py +0 -0
  102. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/streamed.py +0 -0
  103. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/testing/database_test.py +0 -0
  104. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/testing/interceptors.py +0 -0
  105. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/__init__.py +0 -0
  106. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/commit_response.py +0 -0
  107. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/keys.py +0 -0
  108. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/mutation.py +0 -0
  109. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/query_plan.py +0 -0
  110. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/result_set.py +0 -0
  111. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/spanner.py +0 -0
  112. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/transaction.py +0 -0
  113. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google/cloud/spanner_v1/types/type.py +0 -0
  114. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google_cloud_spanner.egg-info/SOURCES.txt +0 -0
  115. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google_cloud_spanner.egg-info/dependency_links.txt +0 -0
  116. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google_cloud_spanner.egg-info/not-zip-safe +0 -0
  117. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google_cloud_spanner.egg-info/requires.txt +0 -0
  118. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/google_cloud_spanner.egg-info/top_level.txt +0 -0
  119. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/setup.cfg +0 -0
  120. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/setup.py +0 -0
  121. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/__init__.py +0 -0
  122. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/_fixtures.py +0 -0
  123. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/_helpers.py +0 -0
  124. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/__init__.py +0 -0
  125. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/_helpers.py +0 -0
  126. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/_sample_data.py +0 -0
  127. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/conftest.py +0 -0
  128. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_backup_api.py +0 -0
  129. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_instance_api.py +0 -0
  130. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/test_streaming_chunking.py +0 -0
  131. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/utils/__init__.py +0 -0
  132. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/utils/clear_streaming.py +0 -0
  133. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/utils/populate_streaming.py +0 -0
  134. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/utils/scrub_instances.py +0 -0
  135. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/system/utils/streaming_utils.py +0 -0
  136. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/__init__.py +0 -0
  137. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/__init__.py +0 -0
  138. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/spanner_admin_database_v1/__init__.py +0 -0
  139. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/spanner_admin_database_v1/test_database_admin.py +0 -0
  140. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/spanner_admin_instance_v1/__init__.py +0 -0
  141. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/spanner_admin_instance_v1/test_instance_admin.py +0 -0
  142. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/spanner_v1/__init__.py +0 -0
  143. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/gapic/spanner_v1/test_spanner.py +0 -0
  144. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/__init__.py +0 -0
  145. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test__helpers.py +0 -0
  146. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_batch_dml_executor.py +0 -0
  147. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_checksum.py +0 -0
  148. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_connect.py +0 -0
  149. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_globals.py +0 -0
  150. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_parser.py +0 -0
  151. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_transaction_helper.py +0 -0
  152. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_types.py +0 -0
  153. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/spanner_dbapi/test_utils.py +0 -0
  154. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/streaming-read-acceptance-test.json +0 -0
  155. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test__helpers.py +0 -0
  156. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test__opentelemetry_tracing.py +0 -0
  157. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_backup.py +0 -0
  158. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_client.py +0 -0
  159. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_instance.py +0 -0
  160. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_keyset.py +0 -0
  161. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_packaging.py +0 -0
  162. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_param_types.py +0 -0
  163. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_pool.py +0 -0
  164. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_session.py +0 -0
  165. {google-cloud-spanner-3.42.0 → google-cloud-spanner-3.43.0}/tests/unit/test_streamed.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: google-cloud-spanner
3
- Version: 3.42.0
3
+ Version: 3.43.0
4
4
  Summary: Google Cloud Spanner API client library
5
5
  Home-page: https://github.com/googleapis/python-spanner
6
6
  Author: Google LLC
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "3.42.0" # {x-release-please-version}
16
+ __version__ = "3.43.0" # {x-release-please-version}
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "3.42.0" # {x-release-please-version}
16
+ __version__ = "3.43.0" # {x-release-please-version}
@@ -18,13 +18,13 @@ from google.cloud.spanner_v1 import param_types
18
18
  SQL_LIST_TABLES = """
19
19
  SELECT table_name
20
20
  FROM information_schema.tables
21
- WHERE table_catalog = '' AND table_schema = ''
21
+ WHERE table_catalog = '' AND table_schema = @table_schema
22
22
  """
23
23
 
24
24
  SQL_GET_TABLE_COLUMN_SCHEMA = """
25
25
  SELECT COLUMN_NAME, IS_NULLABLE, SPANNER_TYPE
26
26
  FROM INFORMATION_SCHEMA.COLUMNS
27
- WHERE TABLE_SCHEMA = '' AND TABLE_NAME = @table_name
27
+ WHERE TABLE_SCHEMA = @table_schema AND TABLE_NAME = @table_name
28
28
  """
29
29
 
30
30
  # This table maps spanner_types to Spanner's data type sizes as per
@@ -105,6 +105,8 @@ def execute(cursor: "Cursor", parsed_statement: ParsedStatement):
105
105
  )
106
106
  if statement_type == ClientSideStatementType.RUN_PARTITIONED_QUERY:
107
107
  return connection.run_partitioned_query(parsed_statement)
108
+ if statement_type == ClientSideStatementType.SET_AUTOCOMMIT_DML_MODE:
109
+ return connection._set_autocommit_dml_mode(parsed_statement)
108
110
 
109
111
 
110
112
  def _get_streamed_result_set(column_name, type_code, column_values):
@@ -38,6 +38,9 @@ RE_RUN_PARTITION = re.compile(r"^\s*(RUN)\s+(PARTITION)\s+(.+)", re.IGNORECASE)
38
38
  RE_RUN_PARTITIONED_QUERY = re.compile(
39
39
  r"^\s*(RUN)\s+(PARTITIONED)\s+(QUERY)\s+(.+)", re.IGNORECASE
40
40
  )
41
+ RE_SET_AUTOCOMMIT_DML_MODE = re.compile(
42
+ r"^\s*(SET)\s+(AUTOCOMMIT_DML_MODE)\s+(=)\s+(.+)", re.IGNORECASE
43
+ )
41
44
 
42
45
 
43
46
  def parse_stmt(query):
@@ -82,6 +85,10 @@ def parse_stmt(query):
82
85
  match = re.search(RE_RUN_PARTITION, query)
83
86
  client_side_statement_params.append(match.group(3))
84
87
  client_side_statement_type = ClientSideStatementType.RUN_PARTITION
88
+ elif RE_SET_AUTOCOMMIT_DML_MODE.match(query):
89
+ match = re.search(RE_SET_AUTOCOMMIT_DML_MODE, query)
90
+ client_side_statement_params.append(match.group(4))
91
+ client_side_statement_type = ClientSideStatementType.SET_AUTOCOMMIT_DML_MODE
85
92
  if client_side_statement_type is not None:
86
93
  return ParsedStatement(
87
94
  StatementType.CLIENT_SIDE,
@@ -23,6 +23,7 @@ from google.cloud.spanner_dbapi.batch_dml_executor import BatchMode, BatchDmlExe
23
23
  from google.cloud.spanner_dbapi.parse_utils import _get_statement_type
24
24
  from google.cloud.spanner_dbapi.parsed_statement import (
25
25
  StatementType,
26
+ AutocommitDmlMode,
26
27
  )
27
28
  from google.cloud.spanner_dbapi.partition_helper import PartitionId
28
29
  from google.cloud.spanner_dbapi.parsed_statement import ParsedStatement, Statement
@@ -116,6 +117,26 @@ class Connection:
116
117
  self._batch_mode = BatchMode.NONE
117
118
  self._batch_dml_executor: BatchDmlExecutor = None
118
119
  self._transaction_helper = TransactionRetryHelper(self)
120
+ self._autocommit_dml_mode: AutocommitDmlMode = AutocommitDmlMode.TRANSACTIONAL
121
+
122
+ @property
123
+ def spanner_client(self):
124
+ """Client for interacting with Cloud Spanner API. This property exposes
125
+ the spanner client so that underlying methods can be accessed.
126
+ """
127
+ return self._instance._client
128
+
129
+ @property
130
+ def current_schema(self):
131
+ """schema name for this connection.
132
+
133
+ :rtype: str
134
+ :returns: the current default schema of this connection. Currently, this
135
+ is always "" for GoogleSQL and "public" for PostgreSQL databases.
136
+ """
137
+ if self.database is None:
138
+ raise ValueError("database property not set on the connection")
139
+ return self.database.default_schema_name
119
140
 
120
141
  @property
121
142
  def autocommit(self):
@@ -148,6 +169,23 @@ class Connection:
148
169
  """
149
170
  return self._database
150
171
 
172
+ @property
173
+ def autocommit_dml_mode(self):
174
+ """Modes for executing DML statements in autocommit mode for this connection.
175
+
176
+ The DML autocommit modes are:
177
+ 1) TRANSACTIONAL - DML statements are executed as single read-write transaction.
178
+ After successful execution, the DML statement is guaranteed to have been applied
179
+ exactly once to the database.
180
+
181
+ 2) PARTITIONED_NON_ATOMIC - DML statements are executed as partitioned DML transactions.
182
+ If an error occurs during the execution of the DML statement, it is possible that the
183
+ statement has been applied to some but not all of the rows specified in the statement.
184
+
185
+ :rtype: :class:`~google.cloud.spanner_dbapi.parsed_statement.AutocommitDmlMode`
186
+ """
187
+ return self._autocommit_dml_mode
188
+
151
189
  @property
152
190
  @deprecated(
153
191
  reason="This method is deprecated. Use _spanner_transaction_started field"
@@ -558,6 +596,37 @@ class Connection:
558
596
  partitioned_query, statement.params, statement.param_types
559
597
  )
560
598
 
599
+ @check_not_closed
600
+ def _set_autocommit_dml_mode(
601
+ self,
602
+ parsed_statement: ParsedStatement,
603
+ ):
604
+ autocommit_dml_mode_str = parsed_statement.client_side_statement_params[0]
605
+ autocommit_dml_mode = AutocommitDmlMode[autocommit_dml_mode_str.upper()]
606
+ self.set_autocommit_dml_mode(autocommit_dml_mode)
607
+
608
+ def set_autocommit_dml_mode(
609
+ self,
610
+ autocommit_dml_mode,
611
+ ):
612
+ """
613
+ Sets the mode for executing DML statements in autocommit mode for this connection.
614
+ This mode is only used when the connection is in autocommit mode, and may only
615
+ be set while the transaction is in autocommit mode and not in a temporary transaction.
616
+ """
617
+
618
+ if self._client_transaction_started is True:
619
+ raise ProgrammingError(
620
+ "Cannot set autocommit DML mode while not in autocommit mode or while a transaction is active."
621
+ )
622
+ if self.read_only is True:
623
+ raise ProgrammingError(
624
+ "Cannot set autocommit DML mode for a read-only connection."
625
+ )
626
+ if self._batch_mode is not BatchMode.NONE:
627
+ raise ProgrammingError("Cannot set autocommit DML mode while in a batch.")
628
+ self._autocommit_dml_mode = autocommit_dml_mode
629
+
561
630
  def _partitioned_query_validation(self, partitioned_query, statement):
562
631
  if _get_statement_type(Statement(partitioned_query)) is not StatementType.QUERY:
563
632
  raise ProgrammingError(
@@ -657,9 +726,10 @@ def connect(
657
726
  raise ValueError("project in url does not match client object project")
658
727
 
659
728
  instance = client.instance(instance_id)
660
- conn = Connection(
661
- instance, instance.database(database_id, pool=pool) if database_id else None
662
- )
729
+ database = None
730
+ if database_id:
731
+ database = instance.database(database_id, pool=pool)
732
+ conn = Connection(instance, database)
663
733
  if pool is not None:
664
734
  conn._own_pool = False
665
735
 
@@ -45,6 +45,7 @@ from google.cloud.spanner_dbapi.parsed_statement import (
45
45
  StatementType,
46
46
  Statement,
47
47
  ParsedStatement,
48
+ AutocommitDmlMode,
48
49
  )
49
50
  from google.cloud.spanner_dbapi.transaction_helper import CursorStatementType
50
51
  from google.cloud.spanner_dbapi.utils import PeekIterator
@@ -272,6 +273,17 @@ class Cursor(object):
272
273
  self._batch_DDLs(sql)
273
274
  if not self.connection._client_transaction_started:
274
275
  self.connection.run_prior_DDL_statements()
276
+ elif (
277
+ self.connection.autocommit_dml_mode
278
+ is AutocommitDmlMode.PARTITIONED_NON_ATOMIC
279
+ ):
280
+ self._row_count = self.connection.database.execute_partitioned_dml(
281
+ sql,
282
+ params=args,
283
+ param_types=self._parsed_statement.statement.param_types,
284
+ request_options=self.connection.request_options,
285
+ )
286
+ self._result_set = None
275
287
  else:
276
288
  self._execute_in_rw_transaction()
277
289
 
@@ -510,13 +522,17 @@ class Cursor(object):
510
522
  raise ProgrammingError("no results to return")
511
523
  return self._itr
512
524
 
513
- def list_tables(self):
525
+ def list_tables(self, schema_name=""):
514
526
  """List the tables of the linked Database.
515
527
 
516
528
  :rtype: list
517
529
  :returns: The list of tables within the Database.
518
530
  """
519
- return self.run_sql_in_snapshot(_helpers.SQL_LIST_TABLES)
531
+ return self.run_sql_in_snapshot(
532
+ sql=_helpers.SQL_LIST_TABLES,
533
+ params={"table_schema": schema_name},
534
+ param_types={"table_schema": spanner.param_types.STRING},
535
+ )
520
536
 
521
537
  def run_sql_in_snapshot(self, sql, params=None, param_types=None):
522
538
  # Some SQL e.g. for INFORMATION_SCHEMA cannot be run in read-write transactions
@@ -528,11 +544,14 @@ class Cursor(object):
528
544
  with self.connection.database.snapshot() as snapshot:
529
545
  return list(snapshot.execute_sql(sql, params, param_types))
530
546
 
531
- def get_table_column_schema(self, table_name):
547
+ def get_table_column_schema(self, table_name, schema_name=""):
532
548
  rows = self.run_sql_in_snapshot(
533
549
  sql=_helpers.SQL_GET_TABLE_COLUMN_SCHEMA,
534
- params={"table_name": table_name},
535
- param_types={"table_name": spanner.param_types.STRING},
550
+ params={"schema_name": schema_name, "table_name": table_name},
551
+ param_types={
552
+ "schema_name": spanner.param_types.STRING,
553
+ "table_name": spanner.param_types.STRING,
554
+ },
536
555
  )
537
556
 
538
557
  column_details = {}
@@ -154,7 +154,9 @@ RE_WITH = re.compile(r"^\s*(WITH)", re.IGNORECASE)
154
154
 
155
155
  # DDL statements follow
156
156
  # https://cloud.google.com/spanner/docs/data-definition-language
157
- RE_DDL = re.compile(r"^\s*(CREATE|ALTER|DROP|GRANT|REVOKE)", re.IGNORECASE | re.DOTALL)
157
+ RE_DDL = re.compile(
158
+ r"^\s*(CREATE|ALTER|DROP|GRANT|REVOKE|RENAME)", re.IGNORECASE | re.DOTALL
159
+ )
158
160
 
159
161
  RE_IS_INSERT = re.compile(r"^\s*(INSERT)", re.IGNORECASE | re.DOTALL)
160
162
 
@@ -36,6 +36,12 @@ class ClientSideStatementType(Enum):
36
36
  PARTITION_QUERY = 9
37
37
  RUN_PARTITION = 10
38
38
  RUN_PARTITIONED_QUERY = 11
39
+ SET_AUTOCOMMIT_DML_MODE = 12
40
+
41
+
42
+ class AutocommitDmlMode(Enum):
43
+ TRANSACTIONAL = 1
44
+ PARTITIONED_NON_ATOMIC = 2
39
45
 
40
46
 
41
47
  @dataclass
@@ -146,7 +146,9 @@ class Batch(_BatchBase):
146
146
  if self.committed is not None:
147
147
  raise ValueError("Batch already committed")
148
148
 
149
- def commit(self, return_commit_stats=False, request_options=None):
149
+ def commit(
150
+ self, return_commit_stats=False, request_options=None, max_commit_delay=None
151
+ ):
150
152
  """Commit mutations to the database.
151
153
 
152
154
  :type return_commit_stats: bool
@@ -160,6 +162,11 @@ class Batch(_BatchBase):
160
162
  If a dict is provided, it must be of the same form as the protobuf
161
163
  message :class:`~google.cloud.spanner_v1.types.RequestOptions`.
162
164
 
165
+ :type max_commit_delay: :class:`datetime.timedelta`
166
+ :param max_commit_delay:
167
+ (Optional) The amount of latency this request is willing to incur
168
+ in order to improve throughput.
169
+
163
170
  :rtype: datetime
164
171
  :returns: timestamp of the committed changes.
165
172
  """
@@ -188,6 +195,7 @@ class Batch(_BatchBase):
188
195
  mutations=self._mutations,
189
196
  single_use_transaction=txn_options,
190
197
  return_commit_stats=return_commit_stats,
198
+ max_commit_delay=max_commit_delay,
191
199
  request_options=request_options,
192
200
  )
193
201
  with trace_call("CloudSpanner.Commit", self._session, trace_attributes):
@@ -12,7 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- """User friendly container for Cloud Spanner Database."""
15
+ """User-friendly container for Cloud Spanner Database."""
16
16
 
17
17
  import copy
18
18
  import functools
@@ -42,6 +42,8 @@ from google.cloud.spanner_admin_database_v1 import UpdateDatabaseDdlRequest
42
42
  from google.cloud.spanner_admin_database_v1.types import DatabaseDialect
43
43
  from google.cloud.spanner_dbapi.partition_helper import BatchTransactionId
44
44
  from google.cloud.spanner_v1 import ExecuteSqlRequest
45
+ from google.cloud.spanner_v1 import Type
46
+ from google.cloud.spanner_v1 import TypeCode
45
47
  from google.cloud.spanner_v1 import TransactionSelector
46
48
  from google.cloud.spanner_v1 import TransactionOptions
47
49
  from google.cloud.spanner_v1 import RequestOptions
@@ -334,8 +336,21 @@ class Database(object):
334
336
  :rtype: :class:`google.cloud.spanner_admin_database_v1.types.DatabaseDialect`
335
337
  :returns: the dialect of the database
336
338
  """
339
+ if self._database_dialect == DatabaseDialect.DATABASE_DIALECT_UNSPECIFIED:
340
+ self.reload()
337
341
  return self._database_dialect
338
342
 
343
+ @property
344
+ def default_schema_name(self):
345
+ """Default schema name for this database.
346
+
347
+ :rtype: str
348
+ :returns: "" for GoogleSQL and "public" for PostgreSQL
349
+ """
350
+ if self.database_dialect == DatabaseDialect.POSTGRESQL:
351
+ return "public"
352
+ return ""
353
+
339
354
  @property
340
355
  def database_role(self):
341
356
  """User-assigned database_role for sessions created by the pool.
@@ -633,8 +648,6 @@ class Database(object):
633
648
  if params is not None:
634
649
  from google.cloud.spanner_v1.transaction import Transaction
635
650
 
636
- if param_types is None:
637
- raise ValueError("Specify 'param_types' when passing 'params'.")
638
651
  params_pb = Transaction._make_params_pb(params, param_types)
639
652
  else:
640
653
  params_pb = {}
@@ -721,7 +734,7 @@ class Database(object):
721
734
  """
722
735
  return SnapshotCheckout(self, **kw)
723
736
 
724
- def batch(self, request_options=None):
737
+ def batch(self, request_options=None, max_commit_delay=None):
725
738
  """Return an object which wraps a batch.
726
739
 
727
740
  The wrapper *must* be used as a context manager, with the batch
@@ -734,10 +747,16 @@ class Database(object):
734
747
  If a dict is provided, it must be of the same form as the protobuf
735
748
  message :class:`~google.cloud.spanner_v1.types.RequestOptions`.
736
749
 
750
+ :type max_commit_delay: :class:`datetime.timedelta`
751
+ :param max_commit_delay:
752
+ (Optional) The amount of latency this request is willing to incur
753
+ in order to improve throughput. Value must be between 0ms and
754
+ 500ms.
755
+
737
756
  :rtype: :class:`~google.cloud.spanner_v1.database.BatchCheckout`
738
757
  :returns: new wrapper
739
758
  """
740
- return BatchCheckout(self, request_options)
759
+ return BatchCheckout(self, request_options, max_commit_delay)
741
760
 
742
761
  def mutation_groups(self):
743
762
  """Return an object which wraps a mutation_group.
@@ -796,9 +815,13 @@ class Database(object):
796
815
 
797
816
  :type kw: dict
798
817
  :param kw: (Optional) keyword arguments to be passed to ``func``.
799
- If passed, "timeout_secs" will be removed and used to
818
+ If passed,
819
+ "timeout_secs" will be removed and used to
800
820
  override the default retry timeout which defines maximum timestamp
801
821
  to continue retrying the transaction.
822
+ "max_commit_delay" will be removed and used to set the
823
+ max_commit_delay for the request. Value must be between
824
+ 0ms and 500ms.
802
825
 
803
826
  :rtype: Any
804
827
  :returns: The return value of ``func``.
@@ -951,20 +974,40 @@ class Database(object):
951
974
  """
952
975
  return Table(table_id, self)
953
976
 
954
- def list_tables(self):
977
+ def list_tables(self, schema="_default"):
955
978
  """List tables within the database.
956
979
 
980
+ :type schema: str
981
+ :param schema: The schema to search for tables, or None for all schemas. Use the special string "_default" to
982
+ search for tables in the default schema of the database.
983
+
957
984
  :type: Iterable
958
985
  :returns:
959
986
  Iterable of :class:`~google.cloud.spanner_v1.table.Table`
960
987
  resources within the current database.
961
988
  """
989
+ if "_default" == schema:
990
+ schema = self.default_schema_name
991
+
962
992
  with self.snapshot() as snapshot:
963
- if self._database_dialect == DatabaseDialect.POSTGRESQL:
964
- where_clause = "WHERE TABLE_SCHEMA = 'public'"
993
+ if schema is None:
994
+ results = snapshot.execute_sql(
995
+ sql=_LIST_TABLES_QUERY.format(""),
996
+ )
965
997
  else:
966
- where_clause = "WHERE SPANNER_STATE = 'COMMITTED'"
967
- results = snapshot.execute_sql(_LIST_TABLES_QUERY.format(where_clause))
998
+ if self._database_dialect == DatabaseDialect.POSTGRESQL:
999
+ where_clause = "WHERE TABLE_SCHEMA = $1"
1000
+ param_name = "p1"
1001
+ else:
1002
+ where_clause = (
1003
+ "WHERE TABLE_SCHEMA = @schema AND SPANNER_STATE = 'COMMITTED'"
1004
+ )
1005
+ param_name = "schema"
1006
+ results = snapshot.execute_sql(
1007
+ sql=_LIST_TABLES_QUERY.format(where_clause),
1008
+ params={param_name: schema},
1009
+ param_types={param_name: Type(code=TypeCode.STRING)},
1010
+ )
968
1011
  for row in results:
969
1012
  yield self.table(row[0])
970
1013
 
@@ -1035,9 +1078,14 @@ class BatchCheckout(object):
1035
1078
  (Optional) Common options for the commit request.
1036
1079
  If a dict is provided, it must be of the same form as the protobuf
1037
1080
  message :class:`~google.cloud.spanner_v1.types.RequestOptions`.
1081
+
1082
+ :type max_commit_delay: :class:`datetime.timedelta`
1083
+ :param max_commit_delay:
1084
+ (Optional) The amount of latency this request is willing to incur
1085
+ in order to improve throughput.
1038
1086
  """
1039
1087
 
1040
- def __init__(self, database, request_options=None):
1088
+ def __init__(self, database, request_options=None, max_commit_delay=None):
1041
1089
  self._database = database
1042
1090
  self._session = self._batch = None
1043
1091
  if request_options is None:
@@ -1046,6 +1094,7 @@ class BatchCheckout(object):
1046
1094
  self._request_options = RequestOptions(request_options)
1047
1095
  else:
1048
1096
  self._request_options = request_options
1097
+ self._max_commit_delay = max_commit_delay
1049
1098
 
1050
1099
  def __enter__(self):
1051
1100
  """Begin ``with`` block."""
@@ -1062,6 +1111,7 @@ class BatchCheckout(object):
1062
1111
  self._batch.commit(
1063
1112
  return_commit_stats=self._database.log_commit_stats,
1064
1113
  request_options=self._request_options,
1114
+ max_commit_delay=self._max_commit_delay,
1065
1115
  )
1066
1116
  finally:
1067
1117
  if self._database.log_commit_stats and self._batch.commit_stats:
@@ -13,4 +13,4 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  #
16
- __version__ = "3.42.0" # {x-release-please-version}
16
+ __version__ = "3.43.0" # {x-release-please-version}
@@ -363,6 +363,8 @@ class Session(object):
363
363
  to continue retrying the transaction.
364
364
  "commit_request_options" will be removed and used to set the
365
365
  request options for the commit request.
366
+ "max_commit_delay" will be removed and used to set the max commit delay for the request.
367
+ "transaction_tag" will be removed and used to set the transaction tag for the request.
366
368
 
367
369
  :rtype: Any
368
370
  :returns: The return value of ``func``.
@@ -372,6 +374,7 @@ class Session(object):
372
374
  """
373
375
  deadline = time.time() + kw.pop("timeout_secs", DEFAULT_RETRY_TIMEOUT_SECS)
374
376
  commit_request_options = kw.pop("commit_request_options", None)
377
+ max_commit_delay = kw.pop("max_commit_delay", None)
375
378
  transaction_tag = kw.pop("transaction_tag", None)
376
379
  attempts = 0
377
380
 
@@ -400,6 +403,7 @@ class Session(object):
400
403
  txn.commit(
401
404
  return_commit_stats=self._database.log_commit_stats,
402
405
  request_options=commit_request_options,
406
+ max_commit_delay=max_commit_delay,
403
407
  )
404
408
  except Aborted as exc:
405
409
  del self._transaction
@@ -410,8 +410,6 @@ class _SnapshotBase(_SessionWrapper):
410
410
  raise ValueError("Transaction ID pending.")
411
411
 
412
412
  if params is not None:
413
- if param_types is None:
414
- raise ValueError("Specify 'param_types' when passing 'params'.")
415
413
  params_pb = Struct(
416
414
  fields={key: _make_value_pb(value) for key, value in params.items()}
417
415
  )
@@ -646,8 +644,6 @@ class _SnapshotBase(_SessionWrapper):
646
644
  raise ValueError("Transaction not started.")
647
645
 
648
646
  if params is not None:
649
- if param_types is None:
650
- raise ValueError("Specify 'param_types' when passing 'params'.")
651
647
  params_pb = Struct(
652
648
  fields={key: _make_value_pb(value) for (key, value) in params.items()}
653
649
  )
@@ -43,13 +43,26 @@ class Table(object):
43
43
  :param database: The database that owns the table.
44
44
  """
45
45
 
46
- def __init__(self, table_id, database):
46
+ def __init__(self, table_id, database, schema_name=None):
47
+ if schema_name is None:
48
+ self._schema_name = database.default_schema_name
49
+ else:
50
+ self._schema_name = schema_name
47
51
  self._table_id = table_id
48
52
  self._database = database
49
53
 
50
54
  # Calculated properties.
51
55
  self._schema = None
52
56
 
57
+ @property
58
+ def schema_name(self):
59
+ """The schema name of the table used in SQL.
60
+
61
+ :rtype: str
62
+ :returns: The table schema name.
63
+ """
64
+ return self._schema_name
65
+
53
66
  @property
54
67
  def table_id(self):
55
68
  """The ID of the table used in SQL.
@@ -59,6 +72,30 @@ class Table(object):
59
72
  """
60
73
  return self._table_id
61
74
 
75
+ @property
76
+ def qualified_table_name(self):
77
+ """The qualified name of the table used in SQL.
78
+
79
+ :rtype: str
80
+ :returns: The qualified table name.
81
+ """
82
+ if self.schema_name == self._database.default_schema_name:
83
+ return self._quote_identifier(self.table_id)
84
+ return "{}.{}".format(
85
+ self._quote_identifier(self.schema_name),
86
+ self._quote_identifier(self.table_id),
87
+ )
88
+
89
+ def _quote_identifier(self, identifier):
90
+ """Quotes the given identifier using the rules of the dialect of the database of this table.
91
+
92
+ :rtype: str
93
+ :returns: The quoted identifier.
94
+ """
95
+ if self._database.database_dialect == DatabaseDialect.POSTGRESQL:
96
+ return '"{}"'.format(identifier)
97
+ return "`{}`".format(identifier)
98
+
62
99
  def exists(self):
63
100
  """Test whether this table exists.
64
101
 
@@ -77,22 +114,27 @@ class Table(object):
77
114
  :rtype: bool
78
115
  :returns: True if the table exists, else false.
79
116
  """
80
- if (
81
- self._database.database_dialect
82
- == DatabaseDialect.DATABASE_DIALECT_UNSPECIFIED
83
- ):
84
- self._database.reload()
85
117
  if self._database.database_dialect == DatabaseDialect.POSTGRESQL:
86
118
  results = snapshot.execute_sql(
87
- _EXISTS_TEMPLATE.format("WHERE TABLE_NAME = $1"),
88
- params={"p1": self.table_id},
89
- param_types={"p1": Type(code=TypeCode.STRING)},
119
+ sql=_EXISTS_TEMPLATE.format(
120
+ "WHERE TABLE_SCHEMA=$1 AND TABLE_NAME = $2"
121
+ ),
122
+ params={"p1": self.schema_name, "p2": self.table_id},
123
+ param_types={
124
+ "p1": Type(code=TypeCode.STRING),
125
+ "p2": Type(code=TypeCode.STRING),
126
+ },
90
127
  )
91
128
  else:
92
129
  results = snapshot.execute_sql(
93
- _EXISTS_TEMPLATE.format("WHERE TABLE_NAME = @table_id"),
94
- params={"table_id": self.table_id},
95
- param_types={"table_id": Type(code=TypeCode.STRING)},
130
+ sql=_EXISTS_TEMPLATE.format(
131
+ "WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = @table_id"
132
+ ),
133
+ params={"schema_name": self.schema_name, "table_id": self.table_id},
134
+ param_types={
135
+ "schema_name": Type(code=TypeCode.STRING),
136
+ "table_id": Type(code=TypeCode.STRING),
137
+ },
96
138
  )
97
139
  return next(iter(results))[0]
98
140
 
@@ -117,7 +159,7 @@ class Table(object):
117
159
  :rtype: list of :class:`~google.cloud.spanner_v1.types.StructType.Field`
118
160
  :returns: The table schema.
119
161
  """
120
- query = _GET_SCHEMA_TEMPLATE.format(self.table_id)
162
+ query = _GET_SCHEMA_TEMPLATE.format(self.qualified_table_name)
121
163
  results = snapshot.execute_sql(query)
122
164
  # Start iterating to force the schema to download.
123
165
  try: