Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit df4ed09

Browse filesBrowse files
authored
Merge branch 'master' into performance
2 parents b50e36f + 74f2269 commit df4ed09
Copy full SHA for df4ed09

File tree

Expand file treeCollapse file tree

9 files changed

+103
-28
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+103
-28
lines changed

‎README.rst

Copy file name to clipboardExpand all lines: README.rst
+8-15Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -283,23 +283,16 @@ were created.
283283
Spanner does not support ``ON DELETE CASCADE`` when creating foreign-key
284284
constraints, so this is not supported in ``django-google-spanner``.
285285

286-
Check constraints aren't supported
287-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
286+
``Unsigned`` datatypes are not supported
287+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
288288

289-
Spanner does not support ``CHECK`` constraints so one isn't created for
290-
`PositiveIntegerField
289+
Spanner does not support ``Unsigned`` datatypes so `PositiveIntegerField
291290
<https://docs.djangoproject.com/en/stable/ref/models/fields/#positiveintegerfield>`__
292-
and `CheckConstraint
293-
<https://docs.djangoproject.com/en/stable/ref/models/constraints/#checkconstraint>`__
294-
can't be used.
295-
296-
No native support for ``DecimalField``
297-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
298-
299-
Spanner's support for `Decimal <https://www.python.org/dev/peps/pep-0327/>`__
300-
types is limited to
301-
`NUMERIC <https://cloud.google.com/spanner/docs/data-types#numeric_types>`__
302-
precision. Higher-precision values can be stored as strings instead.
291+
and `PositiveSmallIntegerField
292+
<https://docs.djangoproject.com/en/3.2/ref/models/fields/#positivesmallintegerfield>`__
293+
are both stored as `Integer type
294+
<https://cloud.google.com/spanner/docs/data-types#integer_type>`__
295+
.
303296

304297
``Meta.order_with_respect_to`` model option isn't supported
305298
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

‎django_spanner/__init__.py

Copy file name to clipboardExpand all lines: django_spanner/__init__.py
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# https://developers.google.com/open-source/licenses/bsd
66

77
import datetime
8+
import os
89

910
# Monkey-patch AutoField to generate a random value since Cloud Spanner can't
1011
# do that.
@@ -24,6 +25,8 @@
2425

2526
__version__ = pkg_resources.get_distribution("django-google-spanner").version
2627

28+
USE_EMULATOR = os.getenv("SPANNER_EMULATOR_HOST") is not None
29+
2730
check_django_compatability()
2831
register_expressions()
2932
register_functions()

‎django_spanner/features.py

Copy file name to clipboardExpand all lines: django_spanner/features.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
184184
"db_functions.comparison.test_cast.CastTests.test_cast_to_decimal_field",
185185
"model_fields.test_decimalfield.DecimalFieldTests.test_fetch_from_db_without_float_rounding",
186186
"model_fields.test_decimalfield.DecimalFieldTests.test_roundtrip_with_trailing_zeros",
187-
# No CHECK constraints in Spanner.
187+
# Spanner does not support unsigned integer field.
188188
"model_fields.test_integerfield.PositiveIntegerFieldTests.test_negative_values",
189189
# Spanner doesn't support the variance the standard deviation database
190190
# functions:

‎django_spanner/schema.py

Copy file name to clipboardExpand all lines: django_spanner/schema.py
+8-2Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.db import NotSupportedError
88
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
99
from django_spanner._opentelemetry_tracing import trace_call
10+
from django_spanner import USE_EMULATOR
1011

1112

1213
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
@@ -472,8 +473,13 @@ def _alter_column_type_sql(self, model, old_field, new_field, new_type):
472473
)
473474

474475
def _check_sql(self, name, check):
475-
# Spanner doesn't support CHECK constraints.
476-
return None
476+
# Emulator does not support check constraints yet.
477+
if USE_EMULATOR:
478+
return None
479+
return self.sql_constraint % {
480+
"name": self.quote_name(name),
481+
"constraint": self.sql_check_constraint % {"check": check},
482+
}
477483

478484
def _unique_sql(self, model, fields, name, condition=None):
479485
# Inline constraints aren't supported, so create the index separately.

‎noxfile.py

Copy file name to clipboardExpand all lines: noxfile.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def lint(session):
4343
session.run("flake8", "django_spanner", "tests")
4444

4545

46-
@nox.session(python="3.6")
46+
@nox.session(python=DEFAULT_PYTHON_VERSION)
4747
def blacken(session):
4848
"""Run black.
4949

‎tests/system/django_spanner/models.py

Copy file name to clipboardExpand all lines: tests/system/django_spanner/models.py
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,16 @@ class Number(models.Model):
2121

2222
def __str__(self):
2323
return str(self.num)
24+
25+
26+
class Event(models.Model):
27+
start_date = models.DateTimeField()
28+
end_date = models.DateTimeField()
29+
30+
class Meta:
31+
constraints = [
32+
models.CheckConstraint(
33+
check=models.Q(end_date__gt=models.F("start_date")),
34+
name="check_start_date",
35+
),
36+
]
+64Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Use of this source code is governed by a BSD-style
4+
# license that can be found in the LICENSE file or at
5+
# https://developers.google.com/open-source/licenses/bsd
6+
7+
from .models import Event
8+
from django.test import TransactionTestCase
9+
import datetime
10+
import unittest
11+
from django.utils import timezone
12+
from google.api_core.exceptions import OutOfRange
13+
from django.db import connection
14+
from django_spanner import USE_EMULATOR
15+
from tests.system.django_spanner.utils import (
16+
setup_instance,
17+
teardown_instance,
18+
setup_database,
19+
teardown_database,
20+
)
21+
22+
23+
@unittest.skipIf(
24+
USE_EMULATOR, "Check Constraint is not implemented in emulator."
25+
)
26+
class TestCheckConstraint(TransactionTestCase):
27+
@classmethod
28+
def setUpClass(cls):
29+
setup_instance()
30+
setup_database()
31+
with connection.schema_editor() as editor:
32+
# Create the table
33+
editor.create_model(Event)
34+
35+
@classmethod
36+
def tearDownClass(cls):
37+
with connection.schema_editor() as editor:
38+
# delete the table
39+
editor.delete_model(Event)
40+
teardown_database()
41+
teardown_instance()
42+
43+
def test_insert_valid_value(self):
44+
"""
45+
Tests model object creation with Event model.
46+
"""
47+
now = timezone.now()
48+
now_plus_10 = now + datetime.timedelta(minutes=10)
49+
event_valid = Event(start_date=now, end_date=now_plus_10)
50+
event_valid.save()
51+
qs1 = Event.objects.filter().values("start_date")
52+
self.assertEqual(qs1[0]["start_date"], now)
53+
# Delete data from Event table.
54+
Event.objects.all().delete()
55+
56+
def test_insert_invalid_value(self):
57+
"""
58+
Tests model object creation with invalid data in Event model.
59+
"""
60+
now = timezone.now()
61+
now_minus_1_day = now - timezone.timedelta(days=1)
62+
event_invalid = Event(start_date=now, end_date=now_minus_1_day)
63+
with self.assertRaises(OutOfRange):
64+
event_invalid.save()

‎tests/system/django_spanner/test_decimal.py

Copy file name to clipboardExpand all lines: tests/system/django_spanner/test_decimal.py
+3-8Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66

77
from .models import Author, Number
88
from django.test import TransactionTestCase
9-
from django.db import connection, ProgrammingError
9+
from django.db import connection
1010
from decimal import Decimal
1111
from tests.system.django_spanner.utils import (
1212
setup_instance,
1313
teardown_instance,
1414
setup_database,
1515
teardown_database,
16-
USE_EMULATOR,
1716
)
1817

1918

@@ -87,12 +86,8 @@ def test_decimal_precision_limit(self):
8786
Tests decimal object precission limit.
8887
"""
8988
num_val = Number(num=Decimal(1) / Decimal(3))
90-
if USE_EMULATOR:
91-
with self.assertRaises(ValueError):
92-
num_val.save()
93-
else:
94-
with self.assertRaises(ProgrammingError):
95-
num_val.save()
89+
with self.assertRaises(ValueError):
90+
num_val.save()
9691

9792
def test_decimal_update(self):
9893
"""

‎tests/system/django_spanner/utils.py

Copy file name to clipboardExpand all lines: tests/system/django_spanner/utils.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
from test_utils.retry import RetryErrors
1616

1717
from django_spanner.creation import DatabaseCreation
18+
from django_spanner import USE_EMULATOR
1819

1920
CREATE_INSTANCE = (
2021
os.getenv("GOOGLE_CLOUD_TESTS_CREATE_SPANNER_INSTANCE") is not None
2122
)
22-
USE_EMULATOR = os.getenv("SPANNER_EMULATOR_HOST") is not None
23+
2324
SPANNER_OPERATION_TIMEOUT_IN_SECONDS = int(
2425
os.getenv("SPANNER_OPERATION_TIMEOUT_IN_SECONDS", 60)
2526
)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.