1from plain.models.db import ProgrammingError
2from plain.utils.functional import cached_property
3
4
5class BaseDatabaseFeatures:
6 # An optional tuple indicating the minimum supported database version.
7 minimum_database_version = None
8 gis_enabled = False
9 # Oracle can't group by LOB (large object) data types.
10 allows_group_by_lob = True
11 allows_group_by_selected_pks = False
12 allows_group_by_select_index = True
13 empty_fetchmany_value = []
14 update_can_self_select = True
15
16 # Does the backend distinguish between '' and None?
17 interprets_empty_strings_as_nulls = False
18
19 # Does the backend allow inserting duplicate NULL rows in a nullable
20 # unique field? All core backends implement this correctly, but other
21 # databases such as SQL Server do not.
22 supports_nullable_unique_constraints = True
23
24 # Does the backend support initially deferrable unique constraints?
25 supports_deferrable_unique_constraints = False
26
27 can_use_chunked_reads = True
28 can_return_columns_from_insert = False
29 can_return_rows_from_bulk_insert = False
30 has_bulk_insert = True
31 uses_savepoints = True
32 can_release_savepoints = False
33
34 # If True, don't use integer foreign keys referring to, e.g., positive
35 # integer primary keys.
36 related_fields_match_type = False
37 allow_sliced_subqueries_with_in = True
38 has_select_for_update = False
39 has_select_for_update_nowait = False
40 has_select_for_update_skip_locked = False
41 has_select_for_update_of = False
42 has_select_for_no_key_update = False
43 # Does the database's SELECT FOR UPDATE OF syntax require a column rather
44 # than a table?
45 select_for_update_of_column = False
46
47 # Does the default test database allow multiple connections?
48 # Usually an indication that the test database is in-memory
49 test_db_allows_multiple_connections = True
50
51 # Can an object be saved without an explicit primary key?
52 supports_unspecified_pk = False
53
54 # Can a fixture contain forward references? i.e., are
55 # FK constraints checked at the end of transaction, or
56 # at the end of each save operation?
57 supports_forward_references = True
58
59 # Does the backend truncate names properly when they are too long?
60 truncates_names = False
61
62 # Is there a REAL datatype in addition to floats/doubles?
63 has_real_datatype = False
64 supports_subqueries_in_group_by = True
65
66 # Does the backend ignore unnecessary ORDER BY clauses in subqueries?
67 ignores_unnecessary_order_by_in_subqueries = True
68
69 # Is there a true datatype for uuid?
70 has_native_uuid_field = False
71
72 # Is there a true datatype for timedeltas?
73 has_native_duration_field = False
74
75 # Does the database driver supports same type temporal data subtraction
76 # by returning the type used to store duration field?
77 supports_temporal_subtraction = False
78
79 # Does the __regex lookup support backreferencing and grouping?
80 supports_regex_backreferencing = True
81
82 # Can date/datetime lookups be performed using a string?
83 supports_date_lookup_using_string = True
84
85 # Can datetimes with timezones be used?
86 supports_timezones = True
87
88 # Does the database have a copy of the zoneinfo database?
89 has_zoneinfo_database = True
90
91 # When performing a GROUP BY, is an ORDER BY NULL required
92 # to remove any ordering?
93 requires_explicit_null_ordering_when_grouping = False
94
95 # Does the backend order NULL values as largest or smallest?
96 nulls_order_largest = False
97
98 # Does the backend support NULLS FIRST and NULLS LAST in ORDER BY?
99 supports_order_by_nulls_modifier = True
100
101 # Does the backend orders NULLS FIRST by default?
102 order_by_nulls_first = False
103
104 # The database's limit on the number of query parameters.
105 max_query_params = None
106
107 # Can an object have an autoincrement primary key of 0?
108 allows_auto_pk_0 = True
109
110 # Do we need to NULL a ForeignKey out, or can the constraint check be
111 # deferred
112 can_defer_constraint_checks = False
113
114 # Does the backend support tablespaces? Default to False because it isn't
115 # in the SQL standard.
116 supports_tablespaces = False
117
118 # Does the backend reset sequences between tests?
119 supports_sequence_reset = True
120
121 # Can the backend introspect the default value of a column?
122 can_introspect_default = True
123
124 # Confirm support for introspected foreign keys
125 # Every database can do this reliably, except MySQL,
126 # which can't do it for MyISAM tables
127 can_introspect_foreign_keys = True
128
129 # Map fields which some backends may not be able to differentiate to the
130 # field it's introspected as.
131 introspected_field_types = {
132 "AutoField": "AutoField",
133 "BigAutoField": "BigAutoField",
134 "BigIntegerField": "BigIntegerField",
135 "BinaryField": "BinaryField",
136 "BooleanField": "BooleanField",
137 "CharField": "CharField",
138 "DurationField": "DurationField",
139 "GenericIPAddressField": "GenericIPAddressField",
140 "IntegerField": "IntegerField",
141 "PositiveBigIntegerField": "PositiveBigIntegerField",
142 "PositiveIntegerField": "PositiveIntegerField",
143 "PositiveSmallIntegerField": "PositiveSmallIntegerField",
144 "SmallAutoField": "SmallAutoField",
145 "SmallIntegerField": "SmallIntegerField",
146 "TimeField": "TimeField",
147 }
148
149 # Can the backend introspect the column order (ASC/DESC) for indexes?
150 supports_index_column_ordering = True
151
152 # Does the backend support introspection of materialized views?
153 can_introspect_materialized_views = False
154
155 # Support for the DISTINCT ON clause
156 can_distinct_on_fields = False
157
158 # Does the backend prevent running SQL queries in broken transactions?
159 atomic_transactions = True
160
161 # Can we roll back DDL in a transaction?
162 can_rollback_ddl = False
163
164 schema_editor_uses_clientside_param_binding = False
165
166 # Does it support operations requiring references rename in a transaction?
167 supports_atomic_references_rename = True
168
169 # Can we issue more than one ALTER COLUMN clause in an ALTER TABLE?
170 supports_combined_alters = False
171
172 # Does it support foreign keys?
173 supports_foreign_keys = True
174
175 # Can it create foreign key constraints inline when adding columns?
176 can_create_inline_fk = True
177
178 # Can an index be renamed?
179 can_rename_index = False
180
181 # Does it automatically index foreign keys?
182 indexes_foreign_keys = True
183
184 # Does it support CHECK constraints?
185 supports_column_check_constraints = True
186 supports_table_check_constraints = True
187 # Does the backend support introspection of CHECK constraints?
188 can_introspect_check_constraints = True
189
190 # Does the backend support 'pyformat' style ("... %(name)s ...", {'name': value})
191 # parameter passing? Note this can be provided by the backend even if not
192 # supported by the Python driver
193 supports_paramstyle_pyformat = True
194
195 # Does the backend require literal defaults, rather than parameterized ones?
196 requires_literal_defaults = False
197
198 # Does the backend require a connection reset after each material schema change?
199 connection_persists_old_columns = False
200
201 # What kind of error does the backend throw when accessing closed cursor?
202 closed_cursor_error_class = ProgrammingError
203
204 # Does 'a' LIKE 'A' match?
205 has_case_insensitive_like = False
206
207 # Suffix for backends that don't support "SELECT xxx;" queries.
208 bare_select_suffix = ""
209
210 # If NULL is implied on columns without needing to be explicitly specified
211 implied_column_null = False
212
213 # Does the backend support "select for update" queries with limit (and offset)?
214 supports_select_for_update_with_limit = True
215
216 # Does the backend ignore null expressions in GREATEST and LEAST queries unless
217 # every expression is null?
218 greatest_least_ignores_nulls = False
219
220 # Can the backend clone databases for parallel test execution?
221 # Defaults to False to allow third-party backends to opt-in.
222 can_clone_databases = False
223
224 # Does the backend consider table names with different casing to
225 # be equal?
226 ignores_table_name_case = False
227
228 # Place FOR UPDATE right after FROM clause. Used on MSSQL.
229 for_update_after_from = False
230
231 # Combinatorial flags
232 supports_select_union = True
233 supports_select_intersection = True
234 supports_select_difference = True
235 supports_slicing_ordering_in_compound = False
236 supports_parentheses_in_compound = True
237 requires_compound_order_by_subquery = False
238
239 # Does the database support SQL 2003 FILTER (WHERE ...) in aggregate
240 # expressions?
241 supports_aggregate_filter_clause = False
242
243 # Does the backend support indexing a TextField?
244 supports_index_on_text_field = True
245
246 # Does the backend support window expressions (expression OVER (...))?
247 supports_over_clause = False
248 supports_frame_range_fixed_distance = False
249 only_supports_unbounded_with_preceding_and_following = False
250
251 # Does the backend support CAST with precision?
252 supports_cast_with_precision = True
253
254 # How many second decimals does the database return when casting a value to
255 # a type with time?
256 time_cast_precision = 6
257
258 # SQL to create a procedure for use by the Plain test suite. The
259 # functionality of the procedure isn't important.
260 create_test_procedure_without_params_sql = None
261 create_test_procedure_with_int_param_sql = None
262
263 # SQL to create a table with a composite primary key for use by the Plain
264 # test suite.
265 create_test_table_with_composite_primary_key = None
266
267 # Does the backend support keyword parameters for cursor.callproc()?
268 supports_callproc_kwargs = False
269
270 # What formats does the backend EXPLAIN syntax support?
271 supported_explain_formats = set()
272
273 # Does the backend support the default parameter in lead() and lag()?
274 supports_default_in_lead_lag = True
275
276 # Does the backend support ignoring constraint or uniqueness errors during
277 # INSERT?
278 supports_ignore_conflicts = True
279 # Does the backend support updating rows on constraint or uniqueness errors
280 # during INSERT?
281 supports_update_conflicts = False
282 supports_update_conflicts_with_target = False
283
284 # Does this backend require casting the results of CASE expressions used
285 # in UPDATE statements to ensure the expression has the correct type?
286 requires_casted_case_in_updates = False
287
288 # Does the backend support partial indexes (CREATE INDEX ... WHERE ...)?
289 supports_partial_indexes = True
290 supports_functions_in_partial_indexes = True
291 # Does the backend support covering indexes (CREATE INDEX ... INCLUDE ...)?
292 supports_covering_indexes = False
293 # Does the backend support indexes on expressions?
294 supports_expression_indexes = True
295 # Does the backend treat COLLATE as an indexed expression?
296 collate_as_index_expression = False
297
298 # Does the backend support boolean expressions in SELECT and GROUP BY
299 # clauses?
300 supports_boolean_expr_in_select_clause = True
301 # Does the backend support comparing boolean expressions in WHERE clauses?
302 # Eg: WHERE (price > 0) IS NOT NULL
303 supports_comparing_boolean_expr = True
304
305 # Does the backend support JSONField?
306 supports_json_field = True
307 # Can the backend introspect a JSONField?
308 can_introspect_json_field = True
309 # Does the backend support primitives in JSONField?
310 supports_primitives_in_json_field = True
311 # Is there a true datatype for JSON?
312 has_native_json_field = False
313 # Does the backend use PostgreSQL-style JSON operators like '->'?
314 has_json_operators = False
315 # Does the backend support __contains and __contained_by lookups for
316 # a JSONField?
317 supports_json_field_contains = True
318 # Does value__d__contains={'f': 'g'} (without a list around the dict) match
319 # {'d': [{'f': 'g'}]}?
320 json_key_contains_list_matching_requires_list = False
321 # Does the backend support JSONObject() database function?
322 has_json_object_function = True
323
324 # Does the backend support column collations?
325 supports_collation_on_charfield = True
326 supports_collation_on_textfield = True
327 # Does the backend support non-deterministic collations?
328 supports_non_deterministic_collations = True
329
330 # Does the backend support column and table comments?
331 supports_comments = False
332 # Does the backend support column comments in ADD COLUMN statements?
333 supports_comments_inline = False
334
335 # Does the backend support the logical XOR operator?
336 supports_logical_xor = False
337
338 # Set to (exception, message) if null characters in text are disallowed.
339 prohibits_null_characters_in_text_exception = None
340
341 # Does the backend support unlimited character columns?
342 supports_unlimited_charfield = False
343
344 # Collation names for use by the Plain test suite.
345 test_collations = {
346 "ci": None, # Case-insensitive.
347 "cs": None, # Case-sensitive.
348 "non_default": None, # Non-default.
349 "swedish_ci": None, # Swedish case-insensitive.
350 }
351 # SQL template override for tests.aggregation.tests.NowUTC
352 test_now_utc_template = None
353
354 def __init__(self, connection):
355 self.connection = connection
356
357 @cached_property
358 def supports_explaining_query_execution(self):
359 """Does this backend support explaining query execution?"""
360 return self.connection.ops.explain_prefix is not None
361
362 @cached_property
363 def supports_transactions(self):
364 """Confirm support for transactions."""
365 with self.connection.cursor() as cursor:
366 cursor.execute("CREATE TABLE ROLLBACK_TEST (X INT)")
367 self.connection.set_autocommit(False)
368 cursor.execute("INSERT INTO ROLLBACK_TEST (X) VALUES (8)")
369 self.connection.rollback()
370 self.connection.set_autocommit(True)
371 cursor.execute("SELECT COUNT(X) FROM ROLLBACK_TEST")
372 (count,) = cursor.fetchone()
373 cursor.execute("DROP TABLE ROLLBACK_TEST")
374 return count == 0
375
376 def allows_group_by_selected_pks_on_model(self, model):
377 if not self.allows_group_by_selected_pks:
378 return False
379 return model._meta.managed