Repository: googleapis/google-cloud-python

Issue:
SPANNER Python API Client - Using database.update_ddl to create/update/drop TABLES
I tried to execute a simple DDL script in python (3.6) to create a table. But I don't know if the update_ddl is used only to manipulate the database schema, or it will also allow me to manipulate the database objects: like TABLES, INDEXES, ... Running regular SQL (inserting, updating, deleting, querying) it all worked like a charm.

Here is a simple example of DDL to create TABLES:
//
def create_tables(instance_id, database_id):
    
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)
    # instance = spanner.Client().instance(instance_id)

    operation = database.update_ddl(database_id, ddl_statements=(
        """CREATE TABLE junk (
            junk_id      INT64 NOT NULL, 
            name         STRING(MAX)
        ) PRIMARY KEY (junk_id)"""
    )

    status = database.create()

    print('Waiting for operation to complete...')
    status.result()
//

**ERROR**:
Traceback (most recent call last):
  File "spannerPython.py", line 77, in <module>
    if __name__ == "__main__":main()
  File "spannerPython.py", line 71, in main
    create_tables(instance_id, database_id)
  File "spannerPython.py", line 17, in create_tables
    ) PRIMARY KEY (junk_id)"""
TypeError: update_ddl() got multiple values for argument 'ddl_statements'


This is the current environment information I have installed:
**OS**:
 System Version:	macOS 10.13.2 (17C205)
  Kernel Version:	Darwin 17.3.0

**Python**
  Version: 3.6.3

**google-cloud-spanner**
  Version: 0.30.0
  Summary: Python Client for Cloud Spanner
  Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python
  Author: Google Cloud Platform
  Author-email: googleapis-publisher@google.com
  License: Apache 2.0
  Location: /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
  Requires: google-api-core, requests, google-cloud-core, grpc-google-iam-v1, google-auth

**pip freeze google**
  gapic-google-cloud-vision-v1==0.90.3
  google-api-core==0.1.4 
  google-api-python-client==1.6.4
  google-auth==1.3.0
  google-auth-httplib2==0.0.3
  google-cloud-core==0.28.0
  google-cloud-spanner==0.30.0
  google-cloud-storage==1.6.0
  google-cloud-vision==0.29.0
  google-gax==0.15.16
  google-resumable-media==0.3.1
  googleapis-common-protos==1.5.3


Discussion:
Hello, Could you try putting the ddl statements in a list?  I'm afk right
now so I can't test it.  But it might be worth a try.

On Fri, Jan 12, 2018, 3:53 AM LMeinhardt <notifications@github.com> wrote:

> I tried to execute a simple DDL script in python (3.6) to create a table.
> So I don't know id the update_ddl is used only to manipulate the database
> schema, or it will also allow me to manipulate the database objects: like
> TABLES, INDEXES, ... Running regular SQL (inserting, updating, deleting,
> querying) it all worked like a charm.
>
> Here is a simple example of DDL to create TABLES:
> //
> def create_tables(instance_id, database_id):
>
> spanner_client = spanner.Client()
> instance = spanner_client.instance(instance_id)
> database = instance.database(database_id)
> # instance = spanner.Client().instance(instance_id)
>
> operation = database.update_ddl(database_id, ddl_statements=(
>     """CREATE TABLE junk (
>         junk_id      INT64 NOT NULL,
>         name         STRING(MAX)
>     ) PRIMARY KEY (junk_id)"""
> )
>
> status = database.create()
>
> print('Waiting for operation to complete...')
> status.result()
>
> //
>
> ERROR:
> Traceback (most recent call last):
> File "spannerPython.py", line 77, in
> if *name* == "*main*":main()
> File "spannerPython.py", line 71, in main
> create_tables(instance_id, database_id)
> File "spannerPython.py", line 17, in create_tables
> ) PRIMARY KEY (junk_id)"""
> TypeError: update_ddl() got multiple values for argument 'ddl_statements'
>
> This is the current environment information I have installed:
> OS:
> System Version: macOS 10.13.2 (17C205)
> Kernel Version: Darwin 17.3.0
> Python
> Version: 3.6.3
> google-cloud-spanner
> Version: 0.30.0
> Summary: Python Client for Cloud Spanner
> Home-page: https://github.com/GoogleCloudPlatform/google-cloud-python
> Author: Google Cloud Platform
> Author-email: googleapis-publisher@google.com
> License: Apache 2.0
> Location:
> /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
> Requires: google-api-core, requests, google-cloud-core,
> grpc-google-iam-v1, google-auth
> pip freeze google
> gapic-google-cloud-vision-v1==0.90.3
> google-api-core==0.1.4
> google-api-python-client==1.6.4
> google-auth==1.3.0
> google-auth-httplib2==0.0.3
> google-cloud-core==0.28.0
> google-cloud-spanner==0.30.0
> google-cloud-storage==1.6.0
> google-cloud-vision==0.29.0
> google-gax==0.15.16
> google-resumable-media==0.3.1
> googleapis-common-protos==1.5.3
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/GoogleCloudPlatform/google-cloud-python/issues/4747>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ADzDDDJ3ck8G7qbC_vPZnjWtdCzFEuGVks5tJ0fDgaJpZM4RcMOC>
> .
>

Fixed the problem, thanks...
//
def create_database(instance_id, database_id):
    """Creates a database and tables for sample data."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    operation = database.update_ddl([
        """CREATE TABLE junk (
            junk_id INT64 NOT NULL,
            name STRING(144),
        ) PRIMARY KEY(junk_id)"""])
        
    print('Waiting for operation to complete...')
    operation.result()

    print('Created tables on database {} - instance {}'.format(
        database_id, instance_id))
//
Do we need to better document the parameter types here:
https://github.com/GoogleCloudPlatform/google-cloud-python/blob/master/spanner/google/cloud/spanner_v1/database.py#L240

On Fri, Jan 12, 2018 at 9:33 AM, LMeinhardt <notifications@github.com>
wrote:

> Fixed the problem, thanks...
> //
> def create_database(instance_id, database_id):
> """Creates a database and tables for sample data."""
> spanner_client = spanner.Client()
> instance = spanner_client.instance(instance_id)
> database = instance.database(database_id)
>
> operation = database.update_ddl([
>     """CREATE TABLE junk (
>         junk_id INT64 NOT NULL,
>         name STRING(144),
>     ) PRIMARY KEY(junk_id)"""])
>
> print('Waiting for operation to complete...')
> operation.result()
>
> print('Created tables on database {} - instance {}'.format(
>     database_id, instance_id))
>
> //
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/GoogleCloudPlatform/google-cloud-python/issues/4747#issuecomment-357300014>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ATdef2cK4qGY_0Ovcj_gZRU5VkzO4Accks5tJ5STgaJpZM4RcMOC>
> .
>


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
@@ -245,6 +245,9 @@ def update_ddl(self, ddl_statements):
         See
         https://cloud.google.com/spanner/reference/rpc/google.spanner.admin.database.v1#google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase
 
+        :type ddl_statements: Sequence[str]
+        :param ddl_statements: a list of DDL statements to use on this database
+
         :rtype: :class:`google.api_core.operation.Operation`
         :returns: an operation instance
         :raises NotFound: if the database does not exist


Test patch: