1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
import operator
import sqlite3
from django.db import transaction
from django.db.backends.base.features import BaseDatabaseFeatures
from django.db.utils import OperationalError
from django.utils.functional import cached_property
from django.utils.version import PY314
from .base import Database
class DatabaseFeatures(BaseDatabaseFeatures):
minimum_database_version = (3, 37)
test_db_allows_multiple_connections = False
supports_unspecified_pk = True
supports_timezones = False
supports_transactions = True
atomic_transactions = False
can_rollback_ddl = True
can_create_inline_fk = False
requires_literal_defaults = True
can_clone_databases = True
supports_temporal_subtraction = True
ignores_table_name_case = True
supports_cast_with_precision = False
time_cast_precision = 3
can_release_savepoints = True
has_case_insensitive_like = True
supports_parentheses_in_compound = False
can_defer_constraint_checks = True
supports_over_clause = True
supports_frame_range_fixed_distance = True
supports_frame_exclusion = True
supports_aggregate_filter_clause = True
supports_aggregate_order_by_clause = Database.sqlite_version_info >= (3, 44, 0)
supports_aggregate_distinct_multiple_argument = False
supports_any_value = True
order_by_nulls_first = True
supports_json_field_contains = False
supports_update_conflicts = True
supports_update_conflicts_with_target = True
supports_stored_generated_columns = True
supports_virtual_generated_columns = True
test_collations = {
"ci": "nocase",
"cs": "binary",
"non_default": "nocase",
"virtual": "nocase",
}
django_test_expected_failures = {
# The django_format_dtdelta() function doesn't properly handle mixed
# Date/DateTime fields and timedeltas.
"expressions.tests.FTimeDeltaTests.test_mixed_comparisons1",
}
insert_test_table_with_defaults = 'INSERT INTO {} ("null") VALUES (1)'
supports_default_keyword_in_insert = False
supports_unlimited_charfield = True
supports_no_precision_decimalfield = True
can_return_columns_from_insert = True
can_return_rows_from_bulk_insert = True
can_return_rows_from_update = True
supports_uuid4_function = True
@cached_property
def supports_uuid7_function(self):
return PY314
@cached_property
def django_test_skips(self):
skips = {
"SQLite stores values rounded to 15 significant digits.": {
"model_fields.test_decimalfield.DecimalFieldTests."
"test_fetch_from_db_without_float_rounding",
},
"SQLite naively remakes the table on field alteration.": {
"schema.tests.SchemaTests.test_unique_no_unnecessary_fk_drops",
"schema.tests.SchemaTests.test_unique_and_reverse_m2m",
"schema.tests.SchemaTests."
"test_alter_field_default_doesnt_perform_queries",
"schema.tests.SchemaTests."
"test_rename_column_renames_deferred_sql_references",
},
"SQLite doesn't support negative precision for ROUND().": {
"db_functions.math.test_round.RoundTests."
"test_null_with_negative_precision",
"db_functions.math.test_round.RoundTests."
"test_decimal_with_negative_precision",
"db_functions.math.test_round.RoundTests."
"test_float_with_negative_precision",
"db_functions.math.test_round.RoundTests."
"test_integer_with_negative_precision",
},
"The actual query cannot be determined on SQLite": {
"backends.base.test_base.ExecuteWrapperTests.test_wrapper_debug",
},
}
if self.connection.is_in_memory_db():
skips.update(
{
"the sqlite backend's close() method is a no-op when using an "
"in-memory database": {
"servers.test_liveserverthread.LiveServerThreadTest."
"test_closes_connections",
"servers.tests.LiveServerTestCloseConnectionTest."
"test_closes_connections",
},
"For SQLite in-memory tests, closing the connection destroys "
"the database.": {
"test_utils.tests.AssertNumQueriesUponConnectionTests."
"test_ignores_connection_configuration_queries",
},
}
)
else:
skips.update(
{
"Only connections to in-memory SQLite databases are passed to the "
"server thread.": {
"servers.tests.LiveServerInMemoryDatabaseLockTest."
"test_in_memory_database_lock",
},
"multiprocessing's start method is checked only for in-memory "
"SQLite databases": {
"backends.sqlite.test_creation.TestDbSignatureTests."
"test_get_test_db_clone_settings_not_supported",
},
}
)
if Database.sqlite_version_info < (3, 47):
skips.update(
{
"SQLite does not parse escaped double quotes in the JSON path "
"notation": {
"model_fields.test_jsonfield.TestQuerying."
"test_lookups_special_chars_double_quotes",
},
}
)
return skips
@cached_property
def introspected_field_types(self):
return {
**super().introspected_field_types,
"BigAutoField": "AutoField",
"DurationField": "BigIntegerField",
"GenericIPAddressField": "CharField",
"SmallAutoField": "AutoField",
}
@property
def max_query_params(self):
"""
SQLite has a variable limit per query. The limit can be changed using
the SQLITE_MAX_VARIABLE_NUMBER compile-time option (which defaults to
32766) or lowered per connection at run-time with
setlimit(SQLITE_LIMIT_VARIABLE_NUMBER, N).
"""
self.connection.ensure_connection()
return self.connection.connection.getlimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER)
@cached_property
def supports_json_field(self):
with self.connection.cursor() as cursor:
try:
with transaction.atomic(self.connection.alias):
cursor.execute('SELECT JSON(\'{"a": "b"}\')')
except OperationalError:
return False
return True
can_introspect_json_field = property(operator.attrgetter("supports_json_field"))
has_json_object_function = property(operator.attrgetter("supports_json_field"))
|