def execute_partitioned_dml(self, dml, params=None, param_types=None): """Execute a partitionable DML statement. :type dml: str :param dml: DML statement :type params: dict, {str -> column value} :param params: values for parameter replacement. Keys must match the names used in ``dml``. :type param_types: dict[str -> Union[dict, .types.Type]] :param param_types: (Optional) maps explicit types for one or more param values; required if parameters are passed. :rtype: int :returns: Count of rows affected by the DML statement. """ if params is not None: if param_types is None: raise ValueError( "Specify 'param_types' when passing 'params'.") params_pb = Struct(fields={ key: _make_value_pb(value) for key, value in params.items() }) else: params_pb = None api = self.spanner_api txn_options = TransactionOptions( partitioned_dml=TransactionOptions.PartitionedDml()) metadata = _metadata_with_prefix(self.name) with SessionCheckout(self._pool) as session: txn = api.begin_transaction(session.name, txn_options, metadata=metadata) txn_selector = TransactionSelector(id=txn.id) restart = functools.partial( api.execute_streaming_sql, session.name, dml, transaction=txn_selector, params=params_pb, param_types=param_types, metadata=metadata, ) iterator = _restart_on_unavailable(restart) result_set = StreamedResultSet(iterator) list(result_set) # consume all partials return result_set.stats.row_count_lower_bound
def execute_pdml(): with SessionCheckout(self._pool) as session: txn = api.begin_transaction(session.name, txn_options, metadata=metadata) txn_selector = TransactionSelector(id=txn.id) restart = functools.partial( api.execute_streaming_sql, session.name, dml, transaction=txn_selector, params=params_pb, param_types=param_types, query_options=query_options, metadata=metadata, ) iterator = _restart_on_unavailable(restart) result_set = StreamedResultSet(iterator) list(result_set) # consume all partials return result_set.stats.row_count_lower_bound
def run_in_transaction(self, func, *args, **kw): """Perform a unit of work in a transaction, retrying on abort. :type func: callable :param func: takes a required positional argument, the transaction, and additional positional / keyword arguments as supplied by the caller. :type args: tuple :param args: additional positional arguments to be passed to ``func``. :type kw: dict :param kw: optional keyword arguments to be passed to ``func``. If passed, "timeout_secs" will be removed and used to override the default timeout. :rtype: :class:`datetime.datetime` :returns: timestamp of committed transaction """ # Sanity check: Is there a transaction already running? # If there is, then raise a red flag. Otherwise, mark that this one # is running. if getattr(self._local, 'transaction_running', False): raise RuntimeError('Spanner does not support nested transactions.') self._local.transaction_running = True # Check out a session and run the function in a transaction; once # done, flip the sanity check bit back. try: with SessionCheckout(self._pool) as session: return session.run_in_transaction(func, *args, **kw) finally: self._local.transaction_running = False
def with_session_wrapper(self, *args, **kwds): if hasattr(self._tldata, "session"): return func(self, self._tldata.session, *args, **kwds) with SpannerStorageSession(self) as spanner_session: with SessionCheckout(self._pool) as session: with session.transaction() as transaction: spanner_session.set_transaction(transaction) return func(self, self._tldata.session, *args, **kwds)
def lock_for_write(self, user, collection): with SpannerStorageSession(self) as spanner_session: collectionid = self._get_collection_id(collection, True) with SessionCheckout(self._pool) as session: with session.transaction() as transaction: spanner_session.set_transaction(transaction) self._lock_write_precondition(spanner_session, user, collectionid) try: yield None except Aborted: raise ConflictError
def run_in_transaction(self, func, *args, **kw): """Perform a unit of work in a transaction, retrying on abort. :type func: callable :param func: takes a required positional argument, the transaction, and additional positional / keyword arguments as supplied by the caller. :type args: tuple :param args: additional positional arguments to be passed to ``func``. :type kw: dict :param kw: (Optional) keyword arguments to be passed to ``func``. If passed, "timeout_secs" will be removed and used to override the default retry timeout which defines maximum timestamp to continue retrying the transaction. :rtype: Any :returns: The return value of ``func``. :raises Exception: reraises any non-ABORT execptions raised by ``func``. """ # Sanity check: Is there a transaction already running? # If there is, then raise a red flag. Otherwise, mark that this one # is running. if getattr(self._local, "transaction_running", False): raise RuntimeError("Spanner does not support nested transactions.") self._local.transaction_running = True # Check out a session and run the function in a transaction; once # done, flip the sanity check bit back. try: with SessionCheckout(self._pool) as session: return session.run_in_transaction(func, *args, **kw) finally: self._local.transaction_running = False
def wrapper(*args, **kwargs): db = Connection.get_instance() with SessionCheckout(db._pool) as session: transaction = session._transaction if transaction is None: transaction = session.transaction() if transaction._transaction_id is None: transaction.begin() try: response = func(transaction=transaction, *args, **kwargs) transaction.commit() return response except Aborted as exc: del transaction raise SpannerException('Transaction Aborted') except GoogleAPICallError: del transaction raise SpannerException('Spanner Db Api Call Error') except Exception: transaction.rollback() raise
def execute_partitioned_dml(self, dml, params=None, param_types=None, query_options=None): """Execute a partitionable DML statement. :type dml: str :param dml: DML statement :type params: dict, {str -> column value} :param params: values for parameter replacement. Keys must match the names used in ``dml``. :type param_types: dict[str -> Union[dict, .types.Type]] :param param_types: (Optional) maps explicit types for one or more param values; required if parameters are passed. :type query_options: :class:`~google.cloud.spanner_v1.proto.ExecuteSqlRequest.QueryOptions` or :class:`dict` :param query_options: (Optional) Query optimizer configuration to use for the given query. If a dict is provided, it must be of the same form as the protobuf message :class:`~google.cloud.spanner_v1.types.QueryOptions` :rtype: int :returns: Count of rows affected by the DML statement. """ query_options = _merge_query_options( self._instance._client._query_options, query_options) if params is not None: if param_types is None: raise ValueError( "Specify 'param_types' when passing 'params'.") params_pb = Struct(fields={ key: _make_value_pb(value) for key, value in params.items() }) else: params_pb = None api = self.spanner_api txn_options = TransactionOptions( partitioned_dml=TransactionOptions.PartitionedDml()) metadata = _metadata_with_prefix(self.name) with SessionCheckout(self._pool) as session: txn = api.begin_transaction(session.name, txn_options, metadata=metadata) txn_selector = TransactionSelector(id=txn.id) restart = functools.partial( api.execute_streaming_sql, session.name, dml, transaction=txn_selector, params=params_pb, param_types=param_types, query_options=query_options, metadata=metadata, ) iterator = _restart_on_unavailable(restart) result_set = StreamedResultSet(iterator) list(result_set) # consume all partials return result_set.stats.row_count_lower_bound