Repository: googleapis/google-cloud-python

Issue:
Cloud Spanner client incorrectly handles NOT_FOUND error returned by create database
While creating a database, is the backend returns NOT_FOUND error, the client assumes it to indicate that instance is not found and thus returns "Instance not found" error message:
https://github.com/GoogleCloudPlatform/google-cloud-python/blob/master/spanner/google/cloud/spanner_v1/database.py#L213

This is not always the case as cloud spanner can return NOT_FOUND in other scenarios. For eg in the "CREATE INDEX ... " ddl statement that table that the index is being created on does not exist it would return a NOT_FOUND.  I think the fix would be to just pass the error message returned by the rpc to the user.

This can be reproduced using:
```python
from google.cloud import spanner

"""Creates a database and tables for pattern 1 sample data."""

spanner_client = spanner.Client()

instance = spanner_client.instance("test-instance")



database = instance.database("bitemporal_pattern1", ddl_statements=[

    """CREATE TABLE MyTable (

        Id        String(36) NOT NULL,

        Field1  STRING(36) NOT NULL

) PRIMARY KEY (Id)"""

,

"""CREATE INDEX IDX ON yTable (Field1)"""

])



operation = database.create()



print('Waiting for operation to complete...')

operation.result()
```


Discussion:
@lukesneeringer @tseaver Any updates on this?

Resolving patch:
diff --git a/spanner/google/cloud/spanner_v1/database.py b/spanner/google/cloud/spanner_v1/database.py
--- a/spanner/google/cloud/spanner_v1/database.py
+++ b/spanner/google/cloud/spanner_v1/database.py
@@ -17,19 +17,20 @@
 import re
 import threading
 
+from google.api_core import exceptions
 import google.auth.credentials
+from google.cloud.exceptions import Conflict
+from google.cloud.exceptions import NotFound
 from google.gax.errors import GaxError
 from google.gax.grpc import exc_to_code
-from google.cloud.spanner_v1.gapic.spanner_client import SpannerClient
 from grpc import StatusCode
 import six
 
 # pylint: disable=ungrouped-imports
-from google.cloud.exceptions import Conflict
-from google.cloud.exceptions import NotFound
 from google.cloud.spanner_v1 import __version__
 from google.cloud.spanner_v1._helpers import _options_with_prefix
 from google.cloud.spanner_v1.batch import Batch
+from google.cloud.spanner_v1.gapic.spanner_client import SpannerClient
 from google.cloud.spanner_v1.pool import BurstyPool
 from google.cloud.spanner_v1.pool import SessionCheckout
 from google.cloud.spanner_v1.session import Session
@@ -208,14 +209,7 @@ def create(self):
                 options=options,
             )
         except GaxError as exc:
-            if exc_to_code(exc.cause) == StatusCode.ALREADY_EXISTS:
-                raise Conflict(self.name)
-            elif exc_to_code(exc.cause) == StatusCode.NOT_FOUND:
-                raise NotFound('Instance not found: {name}'.format(
-                    name=self._instance.name,
-                ))
-            raise
-
+            raise exceptions.from_grpc_error(exc.cause)
         return future
 
     def exists(self):


Test patch:
diff --git a/spanner/tests/system/test_system.py b/spanner/tests/system/test_system.py
--- a/spanner/tests/system/test_system.py
+++ b/spanner/tests/system/test_system.py
@@ -36,6 +36,7 @@
 
 from google.cloud._helpers import UTC
 from google.cloud.exceptions import GrpcRendezvous
+from google.cloud.exceptions import NotFound
 from google.cloud.spanner_v1._helpers import TimestampWithNanoseconds
 from google.cloud.spanner import Client
 from google.cloud.spanner import KeyRange
@@ -282,6 +283,34 @@ def test_create_database(self):
             for database in Config.INSTANCE.list_databases()]
         self.assertIn(temp_db_id, database_ids)
 
+    def test_table_not_found(self):
+        temp_db_id = 'temp_db' + unique_resource_id('_')
+
+        correct_table = 'MyTable'
+        incorrect_table = 'NotMyTable'
+        self.assertNotEqual(correct_table, incorrect_table)
+
+        create_table = (
+            'CREATE TABLE {} (\n'
+            '    Id      STRING(36) NOT NULL,\n'
+            '    Field1  STRING(36) NOT NULL\n'
+            ') PRIMARY KEY (Id)').format(correct_table)
+        index = 'CREATE INDEX IDX ON {} (Field1)'.format(incorrect_table)
+
+        temp_db = Config.INSTANCE.database(
+            temp_db_id,
+            ddl_statements=[
+                create_table,
+                index,
+            ],
+        )
+        self.to_delete.append(temp_db)
+        with self.assertRaises(NotFound) as exc_info:
+            temp_db.create()
+
+        expected = 'Table not found: {0}'.format(incorrect_table)
+        self.assertEqual(exc_info.exception.args, (expected,))
+
     def test_update_database_ddl(self):
         pool = BurstyPool()
         temp_db_id = 'temp_db' + unique_resource_id('_')
diff --git a/spanner/tests/unit/test_database.py b/spanner/tests/unit/test_database.py
--- a/spanner/tests/unit/test_database.py
+++ b/spanner/tests/unit/test_database.py
@@ -284,7 +284,7 @@ def test___ne__(self):
         self.assertNotEqual(database1, database2)
 
     def test_create_grpc_error(self):
-        from google.gax.errors import GaxError
+        from google.api_core.exceptions import GoogleAPICallError
 
         client = _Client()
         api = client.database_admin_api = _FauxDatabaseAdminAPI(
@@ -293,7 +293,7 @@ def test_create_grpc_error(self):
         pool = _Pool()
         database = self._make_one(self.DATABASE_ID, instance, pool=pool)
 
-        with self.assertRaises(GaxError):
+        with self.assertRaises(GoogleAPICallError):
             database.create()
 
         (parent, create_statement, extra_statements,