1
1
# -*- coding: utf-8 -*-
2
2
# Unit and doctests for specific database backends.
3
from __future__ import absolute_import, unicode_literals
3
from __future__ import unicode_literals
7
7
from decimal import Decimal
10
12
from django.conf import settings
13
from django.core.exceptions import ImproperlyConfigured
11
14
from django.core.management.color import no_style
12
15
from django.db import (connection, connections, DEFAULT_DB_ALIAS,
13
16
DatabaseError, IntegrityError, transaction)
14
17
from django.db.backends.signals import connection_created
15
18
from django.db.backends.sqlite3.base import DatabaseOperations
16
19
from django.db.backends.postgresql_psycopg2 import version as pg_version
17
from django.db.backends.util import format_number
20
from django.db.backends.utils import format_number, CursorWrapper
18
21
from django.db.models import Sum, Avg, Variance, StdDev
19
22
from django.db.models.fields import (AutoField, DateField, DateTimeField,
20
23
DecimalField, IntegerField, TimeField)
24
from django.db.models.sql.constants import CURSOR
21
25
from django.db.utils import ConnectionHandler
22
from django.test import (TestCase, skipUnlessDBFeature, skipIfDBFeature,
24
from django.test.utils import override_settings, str_prefix
25
from django.utils import six, unittest
26
from django.test import (TestCase, TransactionTestCase, override_settings,
27
skipUnlessDBFeature, skipIfDBFeature)
28
from django.test.utils import str_prefix, IgnoreAllDeprecationWarningsMixin
29
from django.utils import six
26
30
from django.utils.six.moves import xrange
28
32
from . import models
31
35
class DummyBackendTest(TestCase):
32
37
def test_no_databases(self):
34
39
Test that empty DATABASES setting default to the dummy backend.
39
44
'django.db.backends.dummy')
42
class OracleChecks(unittest.TestCase):
47
@unittest.skipUnless(connection.vendor == 'oracle', "Test only for Oracle")
48
class OracleTests(unittest.TestCase):
44
@unittest.skipUnless(connection.vendor == 'oracle',
45
"No need to check Oracle quote_name semantics")
46
50
def test_quote_name(self):
47
51
# Check that '%' chars are escaped for query execution.
48
52
name = '"SOME%NAME"'
49
53
quoted_name = connection.ops.quote_name(name)
50
54
self.assertEqual(quoted_name % (), name)
52
@unittest.skipUnless(connection.vendor == 'oracle',
53
"No need to check Oracle cursor semantics")
54
56
def test_dbms_session(self):
55
57
# If the backend is Oracle, test that we can call a standard
56
58
# stored procedure through our cursor wrapper.
57
59
from django.db.backends.oracle.base import convert_unicode
59
cursor = connection.cursor()
60
cursor.callproc(convert_unicode('DBMS_SESSION.SET_IDENTIFIER'),
61
[convert_unicode('_django_testing!')])
61
with connection.cursor() as cursor:
62
cursor.callproc(convert_unicode('DBMS_SESSION.SET_IDENTIFIER'),
63
[convert_unicode('_django_testing!')])
63
@unittest.skipUnless(connection.vendor == 'oracle',
64
"No need to check Oracle cursor semantics")
65
65
def test_cursor_var(self):
66
66
# If the backend is Oracle, test that we can pass cursor variables
67
67
# as query parameters.
68
68
from django.db.backends.oracle.base import Database
70
cursor = connection.cursor()
71
var = cursor.var(Database.STRING)
72
cursor.execute("BEGIN %s := 'X'; END; ", [var])
73
self.assertEqual(var.getvalue(), 'X')
70
with connection.cursor() as cursor:
71
var = cursor.var(Database.STRING)
72
cursor.execute("BEGIN %s := 'X'; END; ", [var])
73
self.assertEqual(var.getvalue(), 'X')
75
@unittest.skipUnless(connection.vendor == 'oracle',
76
"No need to check Oracle cursor semantics")
77
75
def test_long_string(self):
78
76
# If the backend is Oracle, test that we can save a text longer
79
77
# than 4000 chars and read it properly
80
c = connection.cursor()
81
c.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
82
long_str = ''.join([six.text_type(x) for x in xrange(4000)])
83
c.execute('INSERT INTO ltext VALUES (%s)', [long_str])
84
c.execute('SELECT text FROM ltext')
86
self.assertEqual(long_str, row[0].read())
87
c.execute('DROP TABLE ltext')
78
with connection.cursor() as cursor:
79
cursor.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
80
long_str = ''.join(six.text_type(x) for x in xrange(4000))
81
cursor.execute('INSERT INTO ltext VALUES (%s)', [long_str])
82
cursor.execute('SELECT text FROM ltext')
83
row = cursor.fetchone()
84
self.assertEqual(long_str, row[0].read())
85
cursor.execute('DROP TABLE ltext')
89
@unittest.skipUnless(connection.vendor == 'oracle',
90
"No need to check Oracle connection semantics")
91
87
def test_client_encoding(self):
92
88
# If the backend is Oracle, test that the client encoding is set
93
89
# correctly. This was broken under Cygwin prior to r14781.
94
connection.cursor() # Ensure the connection is initialized.
90
connection.ensure_connection()
95
91
self.assertEqual(connection.connection.encoding, "UTF-8")
96
92
self.assertEqual(connection.connection.nencoding, "UTF-8")
98
@unittest.skipUnless(connection.vendor == 'oracle',
99
"No need to check Oracle connection semantics")
100
94
def test_order_of_nls_parameters(self):
101
95
# an 'almost right' datetime should work with configured
102
96
# NLS parameters as per #18465.
103
c = connection.cursor()
104
query = "select 1 from dual where '1936-12-29 00:00' < sysdate"
105
# Test that the query succeeds without errors - pre #18465 this
108
self.assertEqual(c.fetchone()[0], 1)
97
with connection.cursor() as cursor:
98
query = "select 1 from dual where '1936-12-29 00:00' < sysdate"
99
# Test that the query succeeds without errors - pre #18465 this
101
cursor.execute(query)
102
self.assertEqual(cursor.fetchone()[0], 1)
105
@unittest.skipUnless(connection.vendor == 'sqlite', "Test only for SQLite")
106
class SQLiteTests(TestCase):
110
def test_autoincrement(self):
112
Check that auto_increment fields are created with the AUTOINCREMENT
113
keyword in order to be monotonically increasing. Refs #10164.
115
statements = connection.creation.sql_create_model(models.Square,
117
match = re.search('"id" ([^,]+),', statements[0][0])
118
self.assertIsNotNone(match)
119
self.assertEqual('integer NOT NULL PRIMARY KEY AUTOINCREMENT',
120
match.group(1), "Wrong SQL used to create an auto-increment "
123
def test_aggregation(self):
125
#19360: Raise NotImplementedError when aggregating on date/time fields.
127
for aggregate in (Sum, Avg, Variance, StdDev):
128
self.assertRaises(NotImplementedError,
129
models.Item.objects.all().aggregate, aggregate('time'))
130
self.assertRaises(NotImplementedError,
131
models.Item.objects.all().aggregate, aggregate('date'))
132
self.assertRaises(NotImplementedError,
133
models.Item.objects.all().aggregate, aggregate('last_modified'))
135
def test_convert_values_to_handle_null_value(self):
136
convert_values = DatabaseOperations(connection).convert_values
137
self.assertIsNone(convert_values(None, AutoField(primary_key=True)))
138
self.assertIsNone(convert_values(None, DateField()))
139
self.assertIsNone(convert_values(None, DateTimeField()))
140
self.assertIsNone(convert_values(None, DecimalField()))
141
self.assertIsNone(convert_values(None, IntegerField()))
142
self.assertIsNone(convert_values(None, TimeField()))
145
@unittest.skipUnless(connection.vendor == 'postgresql', "Test only for PostgreSQL")
146
class PostgreSQLTests(TestCase):
148
def assert_parses(self, version_string, version):
149
self.assertEqual(pg_version._parse_version(version_string), version)
151
def test_parsing(self):
152
"""Test PostgreSQL version parsing from `SELECT version()` output"""
153
self.assert_parses("PostgreSQL 8.3 beta4", 80300)
154
self.assert_parses("PostgreSQL 8.3", 80300)
155
self.assert_parses("EnterpriseDB 8.3", 80300)
156
self.assert_parses("PostgreSQL 8.3.6", 80306)
157
self.assert_parses("PostgreSQL 8.4beta1", 80400)
158
self.assert_parses("PostgreSQL 8.3.1 on i386-apple-darwin9.2.2, compiled by GCC i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)", 80301)
160
def test_version_detection(self):
161
"""Test PostgreSQL version detection"""
164
class CursorMock(object):
165
"Very simple mock of DB-API cursor"
166
def execute(self, arg):
170
return ["PostgreSQL 8.3"]
175
def __exit__(self, type, value, traceback):
178
class OlderConnectionMock(object):
179
"Mock of psycopg2 (< 2.0.12) connection"
183
# psycopg2 < 2.0.12 code path
184
conn = OlderConnectionMock()
185
self.assertEqual(pg_version.get_version(conn), 80300)
187
def test_connect_and_rollback(self):
189
PostgreSQL shouldn't roll back SET TIME ZONE, even if the first
190
transaction is rolled back (#17062).
192
databases = copy.deepcopy(settings.DATABASES)
193
new_connections = ConnectionHandler(databases)
194
new_connection = new_connections[DEFAULT_DB_ALIAS]
196
# Ensure the database default time zone is different than
197
# the time zone in new_connection.settings_dict. We can
198
# get the default time zone by reset & show.
199
cursor = new_connection.cursor()
200
cursor.execute("RESET TIMEZONE")
201
cursor.execute("SHOW TIMEZONE")
202
db_default_tz = cursor.fetchone()[0]
203
new_tz = 'Europe/Paris' if db_default_tz == 'UTC' else 'UTC'
204
new_connection.close()
206
# Fetch a new connection with the new_tz as default
207
# time zone, run a query and rollback.
208
new_connection.settings_dict['TIME_ZONE'] = new_tz
209
new_connection.enter_transaction_management()
210
cursor = new_connection.cursor()
211
new_connection.rollback()
213
# Now let's see if the rollback rolled back the SET TIME ZONE.
214
cursor.execute("SHOW TIMEZONE")
215
tz = cursor.fetchone()[0]
216
self.assertEqual(new_tz, tz)
218
new_connection.close()
220
def test_connect_non_autocommit(self):
222
The connection wrapper shouldn't believe that autocommit is enabled
223
after setting the time zone when AUTOCOMMIT is False (#21452).
225
databases = copy.deepcopy(settings.DATABASES)
226
databases[DEFAULT_DB_ALIAS]['AUTOCOMMIT'] = False
227
new_connections = ConnectionHandler(databases)
228
new_connection = new_connections[DEFAULT_DB_ALIAS]
230
# Open a database connection.
231
new_connection.cursor()
232
self.assertFalse(new_connection.get_autocommit())
234
new_connection.close()
236
def _select(self, val):
237
with connection.cursor() as cursor:
238
cursor.execute("SELECT %s", (val,))
239
return cursor.fetchone()[0]
241
def test_select_ascii_array(self):
244
self.assertEqual(a[0], b[0])
246
def test_select_unicode_array(self):
249
self.assertEqual(a[0], b[0])
251
def test_lookup_cast(self):
252
from django.db.backends.postgresql_psycopg2.operations import DatabaseOperations
254
do = DatabaseOperations(connection=None)
255
for lookup in ('iexact', 'contains', 'icontains', 'startswith',
256
'istartswith', 'endswith', 'iendswith', 'regex', 'iregex'):
257
self.assertIn('::text', do.lookup_cast(lookup))
260
@unittest.skipUnless(connection.vendor == 'mysql', "Test only for MySQL")
111
261
class MySQLTests(TestCase):
112
@unittest.skipUnless(connection.vendor == 'mysql',
113
"Test valid only for MySQL")
114
263
def test_autoincrement(self):
116
265
Check that auto_increment fields are reset correctly by sql_flush().
281
432
self.assertTrue(obj.pk > 10)
284
class PostgresVersionTest(TestCase):
285
def assert_parses(self, version_string, version):
286
self.assertEqual(pg_version._parse_version(version_string), version)
288
def test_parsing(self):
289
"""Test PostgreSQL version parsing from `SELECT version()` output"""
290
self.assert_parses("PostgreSQL 8.3 beta4", 80300)
291
self.assert_parses("PostgreSQL 8.3", 80300)
292
self.assert_parses("EnterpriseDB 8.3", 80300)
293
self.assert_parses("PostgreSQL 8.3.6", 80306)
294
self.assert_parses("PostgreSQL 8.4beta1", 80400)
295
self.assert_parses("PostgreSQL 8.3.1 on i386-apple-darwin9.2.2, compiled by GCC i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5478)", 80301)
297
def test_version_detection(self):
298
"""Test PostgreSQL version detection"""
301
class CursorMock(object):
302
"Very simple mock of DB-API cursor"
303
def execute(self, arg):
307
return ["PostgreSQL 8.3"]
309
class OlderConnectionMock(object):
310
"Mock of psycopg2 (< 2.0.12) connection"
314
# psycopg2 < 2.0.12 code path
315
conn = OlderConnectionMock()
316
self.assertEqual(pg_version.get_version(conn), 80300)
319
class PostgresNewConnectionTests(TestCase):
321
@unittest.skipUnless(
322
connection.vendor == 'postgresql',
323
"This test applies only to PostgreSQL")
324
def test_connect_and_rollback(self):
326
PostgreSQL shouldn't roll back SET TIME ZONE, even if the first
327
transaction is rolled back (#17062).
329
databases = copy.deepcopy(settings.DATABASES)
330
new_connections = ConnectionHandler(databases)
331
new_connection = new_connections[DEFAULT_DB_ALIAS]
333
# Ensure the database default time zone is different than
334
# the time zone in new_connection.settings_dict. We can
335
# get the default time zone by reset & show.
336
cursor = new_connection.cursor()
337
cursor.execute("RESET TIMEZONE")
338
cursor.execute("SHOW TIMEZONE")
339
db_default_tz = cursor.fetchone()[0]
340
new_tz = 'Europe/Paris' if db_default_tz == 'UTC' else 'UTC'
341
new_connection.close()
343
# Fetch a new connection with the new_tz as default
344
# time zone, run a query and rollback.
345
new_connection.settings_dict['TIME_ZONE'] = new_tz
346
new_connection.enter_transaction_management()
347
cursor = new_connection.cursor()
348
new_connection.rollback()
350
# Now let's see if the rollback rolled back the SET TIME ZONE.
351
cursor.execute("SHOW TIMEZONE")
352
tz = cursor.fetchone()[0]
353
self.assertEqual(new_tz, tz)
355
new_connection.close()
357
@unittest.skipUnless(
358
connection.vendor == 'postgresql',
359
"This test applies only to PostgreSQL")
360
def test_connect_non_autocommit(self):
362
The connection wrapper shouldn't believe that autocommit is enabled
363
after setting the time zone when AUTOCOMMIT is False (#21452).
365
databases = copy.deepcopy(settings.DATABASES)
366
databases[DEFAULT_DB_ALIAS]['AUTOCOMMIT'] = False
367
new_connections = ConnectionHandler(databases)
368
new_connection = new_connections[DEFAULT_DB_ALIAS]
370
# Open a database connection.
371
new_connection.cursor()
372
self.assertFalse(new_connection.get_autocommit())
374
new_connection.close()
377
435
# This test needs to run outside of a transaction, otherwise closing the
378
436
# connection would implicitly rollback and cause problems during teardown.
379
437
class ConnectionCreatedSignalTest(TransactionTestCase):
535
544
@skipUnlessDBFeature('supports_paramstyle_pyformat')
536
545
def test_cursor_execute_with_pyformat(self):
537
#10070: Support pyformat style passing of paramters
546
#10070: Support pyformat style passing of parameters
538
547
args = {'root': 3, 'square': 9}
539
548
self.create_squares(args, 'pyformat', multiple=False)
540
549
self.assertEqual(models.Square.objects.count(), 1)
542
551
@skipUnlessDBFeature('supports_paramstyle_pyformat')
543
552
def test_cursor_executemany_with_pyformat(self):
544
#10070: Support pyformat style passing of paramters
545
args = [{'root': i, 'square': i**2} for i in range(-5, 6)]
553
#10070: Support pyformat style passing of parameters
554
args = [{'root': i, 'square': i ** 2} for i in range(-5, 6)]
546
555
self.create_squares(args, 'pyformat', multiple=True)
547
556
self.assertEqual(models.Square.objects.count(), 11)
548
557
for i in range(-5, 6):
549
558
square = models.Square.objects.get(root=i)
550
self.assertEqual(square.square, i**2)
559
self.assertEqual(square.square, i ** 2)
552
561
@skipUnlessDBFeature('supports_paramstyle_pyformat')
553
562
def test_cursor_executemany_with_pyformat_iterator(self):
554
args = iter({'root': i, 'square': i**2} for i in range(-3, 2))
563
args = iter({'root': i, 'square': i ** 2} for i in range(-3, 2))
555
564
self.create_squares(args, 'pyformat', multiple=True)
556
565
self.assertEqual(models.Square.objects.count(), 5)
558
args = iter({'root': i, 'square': i**2} for i in range(3, 7))
567
args = iter({'root': i, 'square': i ** 2} for i in range(3, 7))
559
568
with override_settings(DEBUG=True):
560
569
# same test for DebugCursorWrapper
561
570
self.create_squares(args, 'pyformat', multiple=True)
985
1017
equal('0.1234567890', 12, 0,
1021
class DBTestSettingsRenamedTests(IgnoreAllDeprecationWarningsMixin, TestCase):
1023
mismatch_msg = ("Connection 'test-deprecation' has mismatched TEST "
1024
"and TEST_* database settings.")
1027
def setUpClass(cls):
1028
# Silence "UserWarning: Overriding setting DATABASES can lead to
1029
# unexpected behavior."
1030
cls.warning_classes.append(UserWarning)
1033
super(DBTestSettingsRenamedTests, self).setUp()
1034
self.handler = ConnectionHandler()
1035
self.db_settings = {'default': {}}
1037
def test_mismatched_database_test_settings_1(self):
1038
# if the TEST setting is used, all TEST_* keys must appear in it.
1039
self.db_settings.update({
1040
'test-deprecation': {
1045
with override_settings(DATABASES=self.db_settings):
1046
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
1047
self.handler.prepare_test_settings('test-deprecation')
1049
def test_mismatched_database_test_settings_2(self):
1050
# if the TEST setting is used, all TEST_* keys must match.
1051
self.db_settings.update({
1052
'test-deprecation': {
1053
'TEST': {'NAME': 'foo'},
1057
with override_settings(DATABASES=self.db_settings):
1058
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
1059
self.handler.prepare_test_settings('test-deprecation')
1061
def test_mismatched_database_test_settings_3(self):
1062
# Verifies the mapping of an aliased key.
1063
self.db_settings.update({
1064
'test-deprecation': {
1065
'TEST': {'CREATE_DB': 'foo'},
1066
'TEST_CREATE': 'bar',
1069
with override_settings(DATABASES=self.db_settings):
1070
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
1071
self.handler.prepare_test_settings('test-deprecation')
1073
def test_mismatched_database_test_settings_4(self):
1074
# Verifies the mapping of an aliased key when the aliased key is missing.
1075
self.db_settings.update({
1076
'test-deprecation': {
1078
'TEST_CREATE': 'bar',
1081
with override_settings(DATABASES=self.db_settings):
1082
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
1083
self.handler.prepare_test_settings('test-deprecation')
1085
def test_mismatched_settings_old_none(self):
1086
self.db_settings.update({
1087
'test-deprecation': {
1088
'TEST': {'CREATE_DB': None},
1092
with override_settings(DATABASES=self.db_settings):
1093
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
1094
self.handler.prepare_test_settings('test-deprecation')
1096
def test_mismatched_settings_new_none(self):
1097
self.db_settings.update({
1098
'test-deprecation': {
1100
'TEST_CREATE': None,
1103
with override_settings(DATABASES=self.db_settings):
1104
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
1105
self.handler.prepare_test_settings('test-deprecation')
1107
def test_matched_test_settings(self):
1108
# should be able to define new settings and the old, if they match
1109
self.db_settings.update({
1110
'test-deprecation': {
1111
'TEST': {'NAME': 'foo'},
1115
with override_settings(DATABASES=self.db_settings):
1116
self.handler.prepare_test_settings('test-deprecation')
1118
def test_new_settings_only(self):
1119
# should be able to define new settings without the old
1120
self.db_settings.update({
1121
'test-deprecation': {
1122
'TEST': {'NAME': 'foo'},
1125
with override_settings(DATABASES=self.db_settings):
1126
self.handler.prepare_test_settings('test-deprecation')
1128
def test_old_settings_only(self):
1129
# should be able to define old settings without the new
1130
self.db_settings.update({
1131
'test-deprecation': {
1135
with override_settings(DATABASES=self.db_settings):
1136
self.handler.prepare_test_settings('test-deprecation')
1138
def test_empty_settings(self):
1139
with override_settings(DATABASES=self.db_settings):
1140
self.handler.prepare_test_settings('default')