Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

django-test-suite: expectations of traditional transactions fail get_or_create_tests #270

Closed
odeke-em opened this issue Jan 8, 2020 · 1 comment · Fixed by #385
Closed
Assignees
Labels
🚨 This issue needs some love. triage me I really want to be triaged.

Comments

@odeke-em
Copy link
Contributor

odeke-em commented Jan 8, 2020

Traditional SQL cursors expect a Transaction in which SQL statements are issued but not yet executed. However, due to the awkwardness of the Cloud Spanner API, there really isn't such an equivalence and even then we can't do reads in that transaction so we can't support the expected transaction.

We need to be able to mark the cursor as not supporting the traditional "transaction".

The reported crash log is below

======================================================================
ERROR: test_create_with_duplicate_primary_key (get_or_create.tests.UpdateOrCreateTestsWithManualPKs)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 554, in update_or_create
    obj = self.select_for_update().get(**kwargs)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 408, in get
    self.model._meta.object_name
get_or_create.models.ManualPrimaryKeyTest.DoesNotExist: ManualPrimaryKeyTest matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 57, in error_remapped_callable
    return callable_(*args, **kwargs)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/grpc/_channel.py", line 824, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/grpc/_channel.py", line 726, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
	status = StatusCode.ALREADY_EXISTS
	details = "Row [1] in table get_or_create_manualprimarykeytest already exists"
	debug_error_string = "{"created":"@1578458284.761438291","description":"Error received from peer ipv4:172.217.4.138:443","file":"src/core/lib/surface/call.cc","file_line":1056,"grpc_message":"Row [1] in table get_or_create_manualprimarykeytest already exists","grpc_status":6}"
>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/emmanuel/.local/lib/python3.7/site-packages/spanner/dbapi/cursor.py", line 93, in execute
    self.__handle_insert(sql, args or None)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/spanner/dbapi/cursor.py", line 139, in __handle_insert
    rows,
  File "/home/emmanuel/.local/lib/python3.7/site-packages/spanner/dbapi/connection.py", line 91, in in_transaction
    return self.__dbhandle.run_in_transaction(fn, *args, **kwargs)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/cloud/spanner_v1/database.py", line 444, in run_in_transaction
    return session.run_in_transaction(func, *args, **kw)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/cloud/spanner_v1/session.py", line 313, in run_in_transaction
    txn.commit()
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/cloud/spanner_v1/transaction.py", line 127, in commit
    metadata=metadata,
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/cloud/spanner_v1/gapic/spanner_client.py", line 1556, in commit
    request, retry=retry, timeout=timeout, metadata=metadata
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/api_core/gapic_v1/method.py", line 143, in __call__
    return wrapped_func(*args, **kwargs)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/api_core/retry.py", line 286, in retry_wrapped_func
    on_error=on_error,
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/api_core/retry.py", line 184, in retry_target
    return target()
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/api_core/timeout.py", line 214, in func_with_timeout
    return func(*args, **kwargs)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/google/api_core/grpc_helpers.py", line 59, in error_remapped_callable
    six.raise_from(exceptions.from_grpc_error(exc), exc)
  File "<string>", line 3, in raise_from
google.api_core.exceptions.AlreadyExists: 409 Row [1] in table get_or_create_manualprimarykeytest already exists

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/spanner/dbapi/cursor.py", line 97, in execute
    raise IntegrityError(e.details if hasattr(e, 'details') else e)
spanner.dbapi.exceptions.IntegrityError: 409 Row [1] in table get_or_create_manualprimarykeytest already exists

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 575, in _create_object_from_params
    obj = self.create(**params)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 422, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/base.py", line 741, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/base.py", line 779, in save_base
    force_update, using, update_fields,
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/base.py", line 870, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/base.py", line 908, in _do_insert
    using=using, raw=raw)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 1186, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 1368, in execute_sql
    cursor.execute(sql, params)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "/home/emmanuel/.local/lib/python3.7/site-packages/spanner/dbapi/cursor.py", line 97, in execute
    raise IntegrityError(e.details if hasattr(e, 'details') else e)
django.db.utils.IntegrityError: 409 Row [1] in table get_or_create_manualprimarykeytest already exists

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/tests/get_or_create/tests.py", line 479, in test_create_with_duplicate_primary_key
    ManualPrimaryKeyTest.objects.update_or_create(id=1, data='Different')
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/manager.py", line 82, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 559, in update_or_create
    obj, created = self._create_object_from_params(kwargs, params, lock=True)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 580, in _create_object_from_params
    return qs.get(**lookup), False
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 402, in get
    num = len(clone)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 256, in __len__
    self._fetch_all()
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 1242, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/query.py", line 55, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/models/sql/compiler.py", line 1133, in execute_sql
    cursor.execute(sql, params)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 76, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/utils.py", line 79, in _execute
    self.db.validate_no_broken_transaction()
  File "/home/emmanuel/Desktop/spanner-orm/django_tests/django/django/db/backends/base/base.py", line 438, in validate_no_broken_transaction
    "An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
@timgraham
Copy link
Contributor

The list of tests that are skipped on CockroachDB (which supports transactions but not savepoints):

'get_or_create.tests.GetOrCreateTests.test_get_or_create_invalid_params',
'get_or_create.tests.GetOrCreateTestsWithManualPKs.test_create_with_duplicate_primary_key',
'get_or_create.tests.GetOrCreateTestsWithManualPKs.test_get_or_create_raises_IntegrityError_plus_traceback', # noqa
'get_or_create.tests.GetOrCreateTestsWithManualPKs.test_savepoint_rollback',
'get_or_create.tests.GetOrCreateThroughManyToMany.test_something',
'get_or_create.tests.UpdateOrCreateTests.test_integrity',
'get_or_create.tests.UpdateOrCreateTests.test_manual_primary_key_test',
'get_or_create.tests.UpdateOrCreateTestsWithManualPKs.test_create_with_duplicate_primary_key',

I imagine this is a similar issue.

odeke-em added a commit that referenced this issue Mar 27, 2020
Ran the various component tests in get_or_create,
filed and grouped tests that fail due to lack of savepoints
in Cloud Spanner, following Tim's advisory in #384.

Fixes #270
Fixes #384
odeke-em added a commit that referenced this issue Mar 28, 2020
Ran the various component tests in get_or_create,
filed and grouped tests that fail due to lack of savepoints
in Cloud Spanner, following Tim's advisory in #384.

Fixes #270
Fixes #384
@yoshi-automation yoshi-automation added 🚨 This issue needs some love. triage me I really want to be triaged. labels Apr 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚨 This issue needs some love. triage me I really want to be triaged.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants