Пример #1
0
def clear_tables(database):
    with database.batch() as batch:
        batch.delete(table='AccountHistory', keyset=spanner.KeySet(all_=True))
        batch.delete(table='Accounts', keyset=spanner.KeySet(all_=True))
        batch.delete(table='Customers', keyset=spanner.KeySet(all_=True))
        if AGGREGATE_BALANCE_SHARDS > 0:
            batch.delete(table='AggregateBalance',
                         keyset=spanner.KeySet(all_=True))
Пример #2
0
def read_only_transaction(instance_id, database_id):
    """Reads data inside of a read-only transaction.
    Within the read-only transaction, or "snapshot", the application sees
    consistent view of the database at a particular timestamp.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot(multi_use=True) as snapshot:
        # Read using SQL.
        results = snapshot.execute_sql(
            'SELECT SingerId, AlbumId, AlbumTitle FROM Albums')

        print('Results from first read:')
        for row in results:
            print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))

        # Perform another read using the `read` method. Even if the data
        # is updated in-between the reads, the snapshot ensures that both
        # return the same data.
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(
            table='Albums',
            columns=(
                'SingerId',
                'AlbumId',
                'AlbumTitle',
            ),
            keyset=keyset,
        )

        print('Results from second read:')
        for row in results:
            print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))
    def test_spanner_update(self):
        _prefex = 'test_update'

        # adding data to perform test
        instance = self._SPANNER_INSTANCE
        database = instance.database(self.TEST_DATABASE)
        data = [
            (_prefex + '1', _prefex + 'inset-1'),
            (_prefex + '2', _prefex + 'inset-2'),
            (_prefex + '3', _prefex + 'inset-3'),
        ]
        with database.batch() as batch:
            batch.insert(table='Users', columns=('UserId', 'Key'), values=data)

        mutations_update = [
            WriteMutation.update('Users', ('UserId', 'Key'),
                                 [(_prefex + '1', _prefex + 'update-1')]),
            WriteMutation.update('Users', ('UserId', 'Key'),
                                 [(_prefex + '2', _prefex + 'update-2')]),
            WriteMutation.delete('Users',
                                 spanner.KeySet(keys=[[_prefex + '3']]))
        ]

        p = beam.Pipeline(argv=self.args)
        _ = (p | beam.Create(mutations_update)
             | WriteToSpanner(project_id=self.project,
                              instance_id=self.instance,
                              database_id=self.TEST_DATABASE))

        res = p.run()
        res.wait_until_finish()
        self.assertEqual(self._count_data(_prefex), 2)
Пример #4
0
    def find_multi(
        cls,
        transaction: Optional[spanner_transaction.Transaction],
        keys: Iterable[Dict[str, Any]],
    ) -> List["ModelObject"]:
        """Retrieves objects from Spanner based on the provided keys.

        Args:
          transaction: The existing transaction to use, or None to start a new
            transaction
          keys: An iterable of dictionaries, each dictionary representing the set of
            primary key values necessary to uniquely identify an object in this
            table.

        Returns:
          A list containing all requested objects that exist in the table (can be
          an empty list)
        """
        key_values = []
        for key in keys:
            key_values.append([key[column] for column in cls.primary_keys])
        keyset = spanner.KeySet(keys=key_values)

        args = [cls.table, cls.columns, keyset]
        results = cls._execute_read(table_apis.find, transaction, args)
        return cls._results_to_models(results)
Пример #5
0
    def test_spanner_write_mutation_groups(self, mock_batch_snapshot_class,
                                           mock_batch_checkout):
        ks = spanner.KeySet(keys=[[1233], [1234]])
        mutation_groups = [
            MutationGroup([
                WriteMutation.insert("roles", ("key", "rolename"),
                                     [('9001233', "mutations-inset-1233")]),
                WriteMutation.insert("roles", ("key", "rolename"),
                                     [('9001234', "mutations-inset-1234")])
            ]),
            MutationGroup([
                WriteMutation.update(
                    "roles", ("key", "rolename"),
                    [('9001234', "mutations-inset-9001233-updated")])
            ]),
            MutationGroup([WriteMutation.delete("roles", ks)])
        ]

        p = TestPipeline()
        _ = (p
             | beam.Create(mutation_groups)
             | WriteToSpanner(project_id=TEST_PROJECT_ID,
                              instance_id=TEST_INSTANCE_ID,
                              database_id=_generate_database_name(),
                              max_batch_size_bytes=100))
        res = p.run()
        res.wait_until_finish()

        metric_results = res.metrics().query(
            MetricsFilter().with_name('SpannerBatches'))
        batches_counter = metric_results['counters'][0]

        self.assertEqual(batches_counter.committed, 3)
        self.assertEqual(batches_counter.attempted, 3)
Пример #6
0
def read_data_with_storing_index(instance_id, database_id):
    """Reads sample data from the database using an index with a storing
    clause.

    The index must exist before running this sample. You can add the index
    by running the `add_soring_index` sample or by running this DDL statement
    against your database:

        CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle)
        STORING (MarketingBudget)

    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.snapshot() as snapshot:
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(table='Albums',
                                columns=('AlbumId', 'AlbumTitle',
                                         'MarketingBudget'),
                                keyset=keyset,
                                index='AlbumsByAlbumTitle2')

        for row in results:
            print(u'AlbumId: {}, AlbumTitle: {}, '
                  'MarketingBudget: {}'.format(*row))
Пример #7
0
def run_batch_query(instance_id, database_id):
    """Runs an example batch query."""

    # Expected Table Format:
    # CREATE TABLE Singers (
    #   SingerId   INT64 NOT NULL,
    #   FirstName  STRING(1024),
    #   LastName   STRING(1024),
    #   SingerInfo BYTES(MAX),
    # ) PRIMARY KEY (SingerId);

    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    # Create the batch transaction and generate partitions
    snapshot = database.batch_snapshot()
    partitions = snapshot.generate_read_batches(
        table="Singers",
        columns=("SingerId", "FirstName", "LastName"),
        keyset=spanner.KeySet(all_=True),
    )

    # Create a pool of workers for the tasks
    start = time.time()
    with concurrent.futures.ThreadPoolExecutor() as executor:
        futures = [executor.submit(process, snapshot, p) for p in partitions]

        for future in concurrent.futures.as_completed(futures, timeout=3600):
            finish, row_ct = future.result()
            elapsed = finish - start
            print(u"Completed {} rows in {} seconds".format(row_ct, elapsed))

    # Clean up
    snapshot.close()
Пример #8
0
    def delete_all_from_table(self, table_name):
        """Delete all values from a given table.

    Args:
        table_name (str): the name of the table to delete from
    """
        with self.database.batch() as batch:
            remaining_values = spanner.KeySet(all_=True)
            batch.delete(table_name, remaining_values)
Пример #9
0
def delete_data(instance_id, database_id):
    """Deletes sample data from the given database.

    The database, table, and data must already exist and can be created using
    `create_database` and `insert_data`.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    singers_to_delete = spanner.KeySet(keys=[[1], [2], [3], [4], [5]])
    albums_to_delete = spanner.KeySet(
        keys=[[1, 1], [1, 2], [2, 1], [2, 2], [2, 3]])

    with database.batch() as batch:
        batch.delete('Albums', albums_to_delete)
        batch.delete('Singers', singers_to_delete)

    print('Deleted data.')
Пример #10
0
 def test_delete_by_key_deletes(self, delete):
     mock_transaction = mock.Mock()
     models.SmallTestModel.delete_by_key(
         key='some-key',
         transaction=mock_transaction,
     )
     delete.assert_called_once_with(
         mock_transaction,
         models.SmallTestModel.table,
         spanner.KeySet(keys=[['some-key']]),
     )
Пример #11
0
    def update_albums(transaction):
        # Read the second album budget.
        second_album_keyset = spanner.KeySet(keys=[(2, 2)])
        second_album_result = transaction.read(
            table='Albums', columns=('MarketingBudget',),
            keyset=second_album_keyset, limit=1)
        second_album_row = list(second_album_result)[0]
        second_album_budget = second_album_row[0]

        transfer_amount = 200000

        if second_album_budget < transfer_amount:
            # Raising an exception will automatically roll back the
            # transaction.
            raise ValueError(
                'The second album doesn\'t have enough funds to transfer')

        # Read the first album's budget.
        first_album_keyset = spanner.KeySet(keys=[(1, 1)])
        first_album_result = transaction.read(
            table='Albums', columns=('MarketingBudget',),
            keyset=first_album_keyset, limit=1)
        first_album_row = list(first_album_result)[0]
        first_album_budget = first_album_row[0]

        # Update the budgets.
        second_album_budget -= transfer_amount
        first_album_budget += transfer_amount
        print(
            'Setting first album\'s budget to {} and the second album\'s '
            'budget to {}.'.format(
                first_album_budget, second_album_budget))

        # Update the rows.
        transaction.update(
            table='Albums',
            columns=(
                'SingerId', 'AlbumId', 'MarketingBudget'),
            values=[
                (1, 1, first_album_budget),
                (2, 2, second_album_budget)])
Пример #12
0
def read_data(instance_id, database_id):
    """Reads sample data from the database."""
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    keyset = spanner.KeySet(all_=True)
    results = database.read(
        table='Albums',
        columns=('SingerId', 'AlbumId', 'AlbumTitle',),
        keyset=keyset,)

    for row in results:
        print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))
Пример #13
0
    def search(self, table_name, column_names=None) -> dict:
        """Get a row from a table with matching ID."""

        if not column_names:
            # TODO: faster lookup on column names
            column_names = self.get_table_mapping().get(table_name).keys()

        with self.database.snapshot() as snapshot:
            result = snapshot.read(
                table=table_name,
                columns=column_names,
                keyset=spanner.KeySet(all_=True),
            )
            for row in result:
                yield dict(zip(column_names, row))
Пример #14
0
    def delete(self, transaction: spanner_transaction.Transaction = None) -> None:
        """Deletes this object from the Spanner database.

        Args:
          transaction: The existing transaction to use, or None to start a new
            transaction
        """
        key = [getattr(self, column) for column in self._primary_keys]
        keyset = spanner.KeySet([key])

        db_api = table_apis.delete
        args = [self._table, keyset]
        if transaction is not None:
            db_api(transaction, *args)
        else:
            self.spanner_api().run_write(db_api, *args)
Пример #15
0
    def row_exists(self, table_name, id_):
        """Check whether a row is exist."""

        exists = False
        with self.database.snapshot() as snapshot:
            result = snapshot.read(
                table=table_name,
                columns=["doc_id"],
                keyset=spanner.KeySet([[id_]]),
                limit=1,
            )
            with suppress(IndexError, NotFound):
                row = list(result)[0]
                if row:
                    exists = True
        return exists
Пример #16
0
def function_read_spanner_generic(data, instancename):
    """Background Cloud Function to be triggered by Pub/Sub listener..
    Args:
         data (dict): The dictionary with data specific to this type of event.
         instancename : Spanner instance name.
    """
    import base64

    if 'data' in data:
        msg = base64.b64decode(data['data']).decode('utf-8')
        parseddata = json.loads(msg)
        productid: int = parseddata["product_id"]
        upc: int = parseddata["sku_upc_nbr"]
        pricelevel = parseddata["fulfillment"]["price_level"]

        spanner_client = spanner.Client()
        instance = spanner_client.instance(instancename)
        database = instance.database('inventory')
        count: int = 0

        try:
            while count < 1000:
                with database.snapshot() as snapshot:
                    keyset = spanner.KeySet(keys=[(int(productid) + int(count),
                                                   int(upc) + int(count))])
                    results = snapshot.read(
                        table='availability_by_productid_upc',
                        columns=(
                            'productid',
                            'upc',
                            'fiaavail',
                        ),
                        keyset=keyset,
                    )

                    for row in results:
                        print(u'productid: {}, upc: {}, fiaavail: {}'.format(
                            *row))
                count += 1
        except Exception as e:
            print(f' Exception occurred : {e} ')

    else:
        print('No data to read')

    print('spanner generic read function completed')
Пример #17
0
    def all(
        cls, transaction: Optional[spanner_transaction.Transaction] = None
    ) -> List["ModelObject"]:
        """Returns all objects of this type stored in Spanner.

        Note: this method should only be called on subclasses of Model that have
        a table associated with it. Violating this will cause an exception to be
        raised.

        Args:
          transaction: The existing transaction to use, or None to start a new
            transaction

        Returns:
          A list of models, one per row in the associated Spanner table
        """
        args = [cls.table, cls.columns, spanner.KeySet(all_=True)]
        results = cls._execute_read(table_apis.find, transaction, args)
        return cls._results_to_models(results)
Пример #18
0
def backup_data(tables):
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)
    counter = 0
    rows = []
    for tab in tables:
        counter = counter+1
        with database.snapshot() as snapshot:
            keyset = spanner.KeySet(all_=True)
            # todo figure out how to specify all columns
            results = snapshot.read(
                table=tab,
                columns=(),
                keyset=keyset
            )
            rows.append(results)
        if counter == 15:
            counter = 0
            make_json(results);
Пример #19
0
    def get(self, table_name, id_, column_names=None) -> dict:
        """Get a row from a table with matching ID."""

        if not column_names:
            # TODO: faster lookup on column names
            column_names = self.get_table_mapping().get(table_name).keys()

        entry = {}

        with self.database.snapshot() as snapshot:
            result = snapshot.read(
                table=table_name,
                columns=column_names,
                keyset=spanner.KeySet([[id_]]),
                limit=1,
            )
            with suppress(IndexError, NotFound):
                row = list(result)[0]
                entry = dict(zip(column_names, row))
        return entry
Пример #20
0
    def delete_by_key(
        cls,
        *,
        transaction: Optional[spanner_transaction.Transaction] = None,
        **keys: Any,
    ) -> None:
        """Deletes rows from Spanner based on the provided primary key.

    Args:
      transaction: The existing transaction to use, or None to start a new
        transaction.
      **keys: The keys provided are the complete set of primary keys for this
        table and the corresponding values make up the unique identifier of the
        object being deleted.
    """
        cls._delete_by_keyset(
            transaction=transaction,
            keyset=spanner.KeySet(
                keys=[[keys[column] for column in cls.primary_keys]]),
        )
Пример #21
0
    def delete_batch(
        cls: Type[T],
        models: List[T],
        *,
        transaction: Optional[spanner_transaction.Transaction] = None,
    ) -> None:
        """Deletes rows from Spanner based on the provided models' primary keys.

    Args:
      models: A list of models to be deleted from Spanner.
      transaction: The existing transaction to use, or None to start a new
        transaction
    """
        key_list = []
        for model in models:
            key_list.append(
                [getattr(model, column) for column in cls.primary_keys])
        cls._delete_by_keyset(
            transaction=transaction,
            keyset=spanner.KeySet(keys=key_list),
        )
Пример #22
0
def read_stale_data(instance_id, database_id):
    """Reads sample data from the database. The data is exactly 15 seconds
    stale."""
    import datetime

    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)
    staleness = datetime.timedelta(seconds=15)

    with database.snapshot(exact_staleness=staleness) as snapshot:
        keyset = spanner.KeySet(all_=True)
        results = snapshot.read(table='Albums',
                                columns=(
                                    'SingerId',
                                    'AlbumId',
                                    'AlbumTitle',
                                ),
                                keyset=keyset)

        for row in results:
            print(u'SingerId: {}, AlbumId: {}, AlbumTitle: {}'.format(*row))
Пример #23
0
def read_data_with_index(instance_id, database_id):
    """Reads sample data from the database using an index.

    The index must exist before running this sample. You can add the index
    by running the `add_index` sample or by running this DDL statement against
    your database:

        CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle)

    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    keyset = spanner.KeySet(all_=True)
    results = database.read(table='Albums',
                            columns=('AlbumId', 'AlbumTitle'),
                            keyset=keyset,
                            index='AlbumsByAlbumTitle')

    for row in results:
        print('AlbumId: {}, AlbumTitle: {}'.format(*row))
Пример #24
0
    def delete_batch(cls,
                     transaction: Optional[spanner_transaction.Transaction],
                     models: List[ModelObject]) -> None:
        """Deletes rows from Spanner based on the provided models' primary keys.

    Args:
      transaction: The existing transaction to use, or None to start a new
        transaction
      models: A list of models to be deleted from Spanner.
    """
        key_list = []
        for model in models:
            key_list.append(
                [getattr(model, column) for column in cls.primary_keys])
        keyset = spanner.KeySet(keys=key_list)

        db_api = table_apis.delete
        args = [cls.table, keyset]
        if transaction is not None:
            db_api(transaction, *args)
        else:
            cls.spanner_api().run_write(db_api, *args)
Пример #25
0
        def update_avail(transaction):
            print('In Update Avail function 1 ')
            # Read the timestamp.
            existing_avail_keyset = spanner.KeySet(keys=[(productid, upc)])
            existing_avail_result = transaction.read(
                table='availability_by_productid_upc',
                columns=('lastmodified', ),
                keyset=existing_avail_keyset,
                limit=1)
            print('In Update Avail function 2 ')

            if existing_avail_result is None:
                print('Start inserting the data in the table ')
                with database.batch() as batch:
                    batch.insert(table='availability_by_productid_upc',
                                 columns=(
                                     'productid',
                                     'upc',
                                     'division',
                                     'fiaavail',
                                     'ordermethod',
                                     'pricelevel',
                                     'pricelevelid',
                                     'returnscode',
                                     'maxqty',
                                     'reasoncode',
                                     'lowavailability',
                                     'shiprep',
                                     'lastmodified',
                                 ),
                                 values=[
                                     (productid, upc, div, avail, ordermethod,
                                      pricelevel, pricelevelid, returnscode,
                                      maxqty, reasoncode, lowavailability,
                                      shiprep, lastmodified)
                                 ])

                print(
                    f' Table has been update for UPC : {upc} and message {msg}'
                )

            else:
                print('Row Exists, Compare the timestamp ')
                existing_avail_row = list(existing_avail_result)[0]
                existing_avail_timestamp = existing_avail_row[0]
                print(
                    f' new timestamp : {lastmodified} and previous timestamp {existing_avail_timestamp}'
                )

                if lastmodified < existing_avail_timestamp:
                    # Raising an exception will automatically roll back the
                    # transaction.
                    raise ValueError(
                        'The data is not latest . Latest record is already present'
                    )

                # Update the rows.
                transaction.update(
                    table='availability_by_productid_upc',
                    columns=('productid', 'upc', 'division', 'fiaavail',
                             'ordermethod', 'pricelevel', 'pricelevelid',
                             'returnscode', 'maxqty', 'reasoncode',
                             'lowavailability', 'shiprep', 'lastmodified'),
                    values=[
                        (productid, upc, div, avail, ordermethod, pricelevel,
                         pricelevelid, returnscode, maxqty, reasoncode,
                         lowavailability, shiprep, lastmodified)
                    ])

                database.run_in_transaction(update_avail)

            print('Transaction complete.')
Пример #26
0
import flask
import requests
import os
from google.cloud import spanner

k = spanner.KeySet(all_=True)

instance_id = 'autofocus-instance'
database_id = 'autofocus-database'

database = None

columns = ['postcardId', 'comment', 'img', 'x', 'y']
defaults = ['', '', '', 0, 0]


def get_db():
    c = spanner.Client(project=os.environ['GCLOUD_PROJECT_NAME'])
    i = c.instance(instance_id)
    d = i.database(database_id)
    return d


def serialize(postcard_tuple):
    return dict(zip(columns, postcard_tuple))


def upsertPostcard(postcard):
    global database
    if not database:
        database = get_db()
Пример #27
0
def delete_customer_record(fxa_id):
    customer_to_delete = spanner.KeySet(keys=[[fxa_id]])
    with spanner_database.batch() as batch:
        batch.delete('customer_record', customer_to_delete)
    return True