394 lines
15 KiB
Python
394 lines
15 KiB
Python
|
from django.db import ProgrammingError
|
||
|
from django.utils.functional import cached_property
|
||
|
|
||
|
|
||
|
class BaseDatabaseFeatures:
|
||
|
# An optional tuple indicating the minimum supported database version.
|
||
|
minimum_database_version = None
|
||
|
gis_enabled = False
|
||
|
# Oracle can't group by LOB (large object) data types.
|
||
|
allows_group_by_lob = True
|
||
|
allows_group_by_selected_pks = False
|
||
|
allows_group_by_select_index = True
|
||
|
empty_fetchmany_value = []
|
||
|
update_can_self_select = True
|
||
|
|
||
|
# Does the backend distinguish between '' and None?
|
||
|
interprets_empty_strings_as_nulls = False
|
||
|
|
||
|
# Does the backend allow inserting duplicate NULL rows in a nullable
|
||
|
# unique field? All core backends implement this correctly, but other
|
||
|
# databases such as SQL Server do not.
|
||
|
supports_nullable_unique_constraints = True
|
||
|
|
||
|
# Does the backend allow inserting duplicate rows when a unique_together
|
||
|
# constraint exists and some fields are nullable but not all of them?
|
||
|
supports_partially_nullable_unique_constraints = True
|
||
|
# Does the backend support initially deferrable unique constraints?
|
||
|
supports_deferrable_unique_constraints = False
|
||
|
|
||
|
can_use_chunked_reads = True
|
||
|
can_return_columns_from_insert = False
|
||
|
can_return_rows_from_bulk_insert = False
|
||
|
has_bulk_insert = True
|
||
|
uses_savepoints = True
|
||
|
can_release_savepoints = False
|
||
|
|
||
|
# If True, don't use integer foreign keys referring to, e.g., positive
|
||
|
# integer primary keys.
|
||
|
related_fields_match_type = False
|
||
|
allow_sliced_subqueries_with_in = True
|
||
|
has_select_for_update = False
|
||
|
has_select_for_update_nowait = False
|
||
|
has_select_for_update_skip_locked = False
|
||
|
has_select_for_update_of = False
|
||
|
has_select_for_no_key_update = False
|
||
|
# Does the database's SELECT FOR UPDATE OF syntax require a column rather
|
||
|
# than a table?
|
||
|
select_for_update_of_column = False
|
||
|
|
||
|
# Does the default test database allow multiple connections?
|
||
|
# Usually an indication that the test database is in-memory
|
||
|
test_db_allows_multiple_connections = True
|
||
|
|
||
|
# Can an object be saved without an explicit primary key?
|
||
|
supports_unspecified_pk = False
|
||
|
|
||
|
# Can a fixture contain forward references? i.e., are
|
||
|
# FK constraints checked at the end of transaction, or
|
||
|
# at the end of each save operation?
|
||
|
supports_forward_references = True
|
||
|
|
||
|
# Does the backend truncate names properly when they are too long?
|
||
|
truncates_names = False
|
||
|
|
||
|
# Is there a REAL datatype in addition to floats/doubles?
|
||
|
has_real_datatype = False
|
||
|
supports_subqueries_in_group_by = True
|
||
|
|
||
|
# Does the backend ignore unnecessary ORDER BY clauses in subqueries?
|
||
|
ignores_unnecessary_order_by_in_subqueries = True
|
||
|
|
||
|
# Is there a true datatype for uuid?
|
||
|
has_native_uuid_field = False
|
||
|
|
||
|
# Is there a true datatype for timedeltas?
|
||
|
has_native_duration_field = False
|
||
|
|
||
|
# Does the database driver supports same type temporal data subtraction
|
||
|
# by returning the type used to store duration field?
|
||
|
supports_temporal_subtraction = False
|
||
|
|
||
|
# Does the __regex lookup support backreferencing and grouping?
|
||
|
supports_regex_backreferencing = True
|
||
|
|
||
|
# Can date/datetime lookups be performed using a string?
|
||
|
supports_date_lookup_using_string = True
|
||
|
|
||
|
# Can datetimes with timezones be used?
|
||
|
supports_timezones = True
|
||
|
|
||
|
# Does the database have a copy of the zoneinfo database?
|
||
|
has_zoneinfo_database = True
|
||
|
|
||
|
# When performing a GROUP BY, is an ORDER BY NULL required
|
||
|
# to remove any ordering?
|
||
|
requires_explicit_null_ordering_when_grouping = False
|
||
|
|
||
|
# Does the backend order NULL values as largest or smallest?
|
||
|
nulls_order_largest = False
|
||
|
|
||
|
# Does the backend support NULLS FIRST and NULLS LAST in ORDER BY?
|
||
|
supports_order_by_nulls_modifier = True
|
||
|
|
||
|
# Does the backend orders NULLS FIRST by default?
|
||
|
order_by_nulls_first = False
|
||
|
|
||
|
# The database's limit on the number of query parameters.
|
||
|
max_query_params = None
|
||
|
|
||
|
# Can an object have an autoincrement primary key of 0?
|
||
|
allows_auto_pk_0 = True
|
||
|
|
||
|
# Do we need to NULL a ForeignKey out, or can the constraint check be
|
||
|
# deferred
|
||
|
can_defer_constraint_checks = False
|
||
|
|
||
|
# Does the backend support tablespaces? Default to False because it isn't
|
||
|
# in the SQL standard.
|
||
|
supports_tablespaces = False
|
||
|
|
||
|
# Does the backend reset sequences between tests?
|
||
|
supports_sequence_reset = True
|
||
|
|
||
|
# Can the backend introspect the default value of a column?
|
||
|
can_introspect_default = True
|
||
|
|
||
|
# Confirm support for introspected foreign keys
|
||
|
# Every database can do this reliably, except MySQL,
|
||
|
# which can't do it for MyISAM tables
|
||
|
can_introspect_foreign_keys = True
|
||
|
|
||
|
# Map fields which some backends may not be able to differentiate to the
|
||
|
# field it's introspected as.
|
||
|
introspected_field_types = {
|
||
|
"AutoField": "AutoField",
|
||
|
"BigAutoField": "BigAutoField",
|
||
|
"BigIntegerField": "BigIntegerField",
|
||
|
"BinaryField": "BinaryField",
|
||
|
"BooleanField": "BooleanField",
|
||
|
"CharField": "CharField",
|
||
|
"DurationField": "DurationField",
|
||
|
"GenericIPAddressField": "GenericIPAddressField",
|
||
|
"IntegerField": "IntegerField",
|
||
|
"PositiveBigIntegerField": "PositiveBigIntegerField",
|
||
|
"PositiveIntegerField": "PositiveIntegerField",
|
||
|
"PositiveSmallIntegerField": "PositiveSmallIntegerField",
|
||
|
"SmallAutoField": "SmallAutoField",
|
||
|
"SmallIntegerField": "SmallIntegerField",
|
||
|
"TimeField": "TimeField",
|
||
|
}
|
||
|
|
||
|
# Can the backend introspect the column order (ASC/DESC) for indexes?
|
||
|
supports_index_column_ordering = True
|
||
|
|
||
|
# Does the backend support introspection of materialized views?
|
||
|
can_introspect_materialized_views = False
|
||
|
|
||
|
# Support for the DISTINCT ON clause
|
||
|
can_distinct_on_fields = False
|
||
|
|
||
|
# Does the backend prevent running SQL queries in broken transactions?
|
||
|
atomic_transactions = True
|
||
|
|
||
|
# Can we roll back DDL in a transaction?
|
||
|
can_rollback_ddl = False
|
||
|
|
||
|
schema_editor_uses_clientside_param_binding = False
|
||
|
|
||
|
# Does it support operations requiring references rename in a transaction?
|
||
|
supports_atomic_references_rename = True
|
||
|
|
||
|
# Can we issue more than one ALTER COLUMN clause in an ALTER TABLE?
|
||
|
supports_combined_alters = False
|
||
|
|
||
|
# Does it support foreign keys?
|
||
|
supports_foreign_keys = True
|
||
|
|
||
|
# Can it create foreign key constraints inline when adding columns?
|
||
|
can_create_inline_fk = True
|
||
|
|
||
|
# Can an index be renamed?
|
||
|
can_rename_index = False
|
||
|
|
||
|
# Does it automatically index foreign keys?
|
||
|
indexes_foreign_keys = True
|
||
|
|
||
|
# Does it support CHECK constraints?
|
||
|
supports_column_check_constraints = True
|
||
|
supports_table_check_constraints = True
|
||
|
# Does the backend support introspection of CHECK constraints?
|
||
|
can_introspect_check_constraints = True
|
||
|
|
||
|
# Does the backend support 'pyformat' style ("... %(name)s ...", {'name': value})
|
||
|
# parameter passing? Note this can be provided by the backend even if not
|
||
|
# supported by the Python driver
|
||
|
supports_paramstyle_pyformat = True
|
||
|
|
||
|
# Does the backend require literal defaults, rather than parameterized ones?
|
||
|
requires_literal_defaults = False
|
||
|
|
||
|
# Does the backend require a connection reset after each material schema change?
|
||
|
connection_persists_old_columns = False
|
||
|
|
||
|
# What kind of error does the backend throw when accessing closed cursor?
|
||
|
closed_cursor_error_class = ProgrammingError
|
||
|
|
||
|
# Does 'a' LIKE 'A' match?
|
||
|
has_case_insensitive_like = False
|
||
|
|
||
|
# Suffix for backends that don't support "SELECT xxx;" queries.
|
||
|
bare_select_suffix = ""
|
||
|
|
||
|
# If NULL is implied on columns without needing to be explicitly specified
|
||
|
implied_column_null = False
|
||
|
|
||
|
# Does the backend support "select for update" queries with limit (and offset)?
|
||
|
supports_select_for_update_with_limit = True
|
||
|
|
||
|
# Does the backend ignore null expressions in GREATEST and LEAST queries unless
|
||
|
# every expression is null?
|
||
|
greatest_least_ignores_nulls = False
|
||
|
|
||
|
# Can the backend clone databases for parallel test execution?
|
||
|
# Defaults to False to allow third-party backends to opt-in.
|
||
|
can_clone_databases = False
|
||
|
|
||
|
# Does the backend consider table names with different casing to
|
||
|
# be equal?
|
||
|
ignores_table_name_case = False
|
||
|
|
||
|
# Place FOR UPDATE right after FROM clause. Used on MSSQL.
|
||
|
for_update_after_from = False
|
||
|
|
||
|
# Combinatorial flags
|
||
|
supports_select_union = True
|
||
|
supports_select_intersection = True
|
||
|
supports_select_difference = True
|
||
|
supports_slicing_ordering_in_compound = False
|
||
|
supports_parentheses_in_compound = True
|
||
|
requires_compound_order_by_subquery = False
|
||
|
|
||
|
# Does the database support SQL 2003 FILTER (WHERE ...) in aggregate
|
||
|
# expressions?
|
||
|
supports_aggregate_filter_clause = False
|
||
|
|
||
|
# Does the backend support indexing a TextField?
|
||
|
supports_index_on_text_field = True
|
||
|
|
||
|
# Does the backend support window expressions (expression OVER (...))?
|
||
|
supports_over_clause = False
|
||
|
supports_frame_range_fixed_distance = False
|
||
|
only_supports_unbounded_with_preceding_and_following = False
|
||
|
|
||
|
# Does the backend support CAST with precision?
|
||
|
supports_cast_with_precision = True
|
||
|
|
||
|
# How many second decimals does the database return when casting a value to
|
||
|
# a type with time?
|
||
|
time_cast_precision = 6
|
||
|
|
||
|
# SQL to create a procedure for use by the Django test suite. The
|
||
|
# functionality of the procedure isn't important.
|
||
|
create_test_procedure_without_params_sql = None
|
||
|
create_test_procedure_with_int_param_sql = None
|
||
|
|
||
|
# SQL to create a table with a composite primary key for use by the Django
|
||
|
# test suite.
|
||
|
create_test_table_with_composite_primary_key = None
|
||
|
|
||
|
# Does the backend support keyword parameters for cursor.callproc()?
|
||
|
supports_callproc_kwargs = False
|
||
|
|
||
|
# What formats does the backend EXPLAIN syntax support?
|
||
|
supported_explain_formats = set()
|
||
|
|
||
|
# Does the backend support the default parameter in lead() and lag()?
|
||
|
supports_default_in_lead_lag = True
|
||
|
|
||
|
# Does the backend support ignoring constraint or uniqueness errors during
|
||
|
# INSERT?
|
||
|
supports_ignore_conflicts = True
|
||
|
# Does the backend support updating rows on constraint or uniqueness errors
|
||
|
# during INSERT?
|
||
|
supports_update_conflicts = False
|
||
|
supports_update_conflicts_with_target = False
|
||
|
|
||
|
# Does this backend require casting the results of CASE expressions used
|
||
|
# in UPDATE statements to ensure the expression has the correct type?
|
||
|
requires_casted_case_in_updates = False
|
||
|
|
||
|
# Does the backend support partial indexes (CREATE INDEX ... WHERE ...)?
|
||
|
supports_partial_indexes = True
|
||
|
supports_functions_in_partial_indexes = True
|
||
|
# Does the backend support covering indexes (CREATE INDEX ... INCLUDE ...)?
|
||
|
supports_covering_indexes = False
|
||
|
# Does the backend support indexes on expressions?
|
||
|
supports_expression_indexes = True
|
||
|
# Does the backend treat COLLATE as an indexed expression?
|
||
|
collate_as_index_expression = False
|
||
|
|
||
|
# Does the database allow more than one constraint or index on the same
|
||
|
# field(s)?
|
||
|
allows_multiple_constraints_on_same_fields = True
|
||
|
|
||
|
# Does the backend support boolean expressions in SELECT and GROUP BY
|
||
|
# clauses?
|
||
|
supports_boolean_expr_in_select_clause = True
|
||
|
# Does the backend support comparing boolean expressions in WHERE clauses?
|
||
|
# Eg: WHERE (price > 0) IS NOT NULL
|
||
|
supports_comparing_boolean_expr = True
|
||
|
|
||
|
# Does the backend support JSONField?
|
||
|
supports_json_field = True
|
||
|
# Can the backend introspect a JSONField?
|
||
|
can_introspect_json_field = True
|
||
|
# Does the backend support primitives in JSONField?
|
||
|
supports_primitives_in_json_field = True
|
||
|
# Is there a true datatype for JSON?
|
||
|
has_native_json_field = False
|
||
|
# Does the backend use PostgreSQL-style JSON operators like '->'?
|
||
|
has_json_operators = False
|
||
|
# Does the backend support __contains and __contained_by lookups for
|
||
|
# a JSONField?
|
||
|
supports_json_field_contains = True
|
||
|
# Does value__d__contains={'f': 'g'} (without a list around the dict) match
|
||
|
# {'d': [{'f': 'g'}]}?
|
||
|
json_key_contains_list_matching_requires_list = False
|
||
|
# Does the backend support JSONObject() database function?
|
||
|
has_json_object_function = True
|
||
|
|
||
|
# Does the backend support column collations?
|
||
|
supports_collation_on_charfield = True
|
||
|
supports_collation_on_textfield = True
|
||
|
# Does the backend support non-deterministic collations?
|
||
|
supports_non_deterministic_collations = True
|
||
|
|
||
|
# Does the backend support column and table comments?
|
||
|
supports_comments = False
|
||
|
# Does the backend support column comments in ADD COLUMN statements?
|
||
|
supports_comments_inline = False
|
||
|
|
||
|
# Does the backend support the logical XOR operator?
|
||
|
supports_logical_xor = False
|
||
|
|
||
|
# Set to (exception, message) if null characters in text are disallowed.
|
||
|
prohibits_null_characters_in_text_exception = None
|
||
|
|
||
|
# Does the backend support unlimited character columns?
|
||
|
supports_unlimited_charfield = False
|
||
|
|
||
|
# Collation names for use by the Django test suite.
|
||
|
test_collations = {
|
||
|
"ci": None, # Case-insensitive.
|
||
|
"cs": None, # Case-sensitive.
|
||
|
"non_default": None, # Non-default.
|
||
|
"swedish_ci": None, # Swedish case-insensitive.
|
||
|
}
|
||
|
# SQL template override for tests.aggregation.tests.NowUTC
|
||
|
test_now_utc_template = None
|
||
|
|
||
|
# A set of dotted paths to tests in Django's test suite that are expected
|
||
|
# to fail on this database.
|
||
|
django_test_expected_failures = set()
|
||
|
# A map of reasons to sets of dotted paths to tests in Django's test suite
|
||
|
# that should be skipped for this database.
|
||
|
django_test_skips = {}
|
||
|
|
||
|
def __init__(self, connection):
|
||
|
self.connection = connection
|
||
|
|
||
|
@cached_property
|
||
|
def supports_explaining_query_execution(self):
|
||
|
"""Does this backend support explaining query execution?"""
|
||
|
return self.connection.ops.explain_prefix is not None
|
||
|
|
||
|
@cached_property
|
||
|
def supports_transactions(self):
|
||
|
"""Confirm support for transactions."""
|
||
|
with self.connection.cursor() as cursor:
|
||
|
cursor.execute("CREATE TABLE ROLLBACK_TEST (X INT)")
|
||
|
self.connection.set_autocommit(False)
|
||
|
cursor.execute("INSERT INTO ROLLBACK_TEST (X) VALUES (8)")
|
||
|
self.connection.rollback()
|
||
|
self.connection.set_autocommit(True)
|
||
|
cursor.execute("SELECT COUNT(X) FROM ROLLBACK_TEST")
|
||
|
(count,) = cursor.fetchone()
|
||
|
cursor.execute("DROP TABLE ROLLBACK_TEST")
|
||
|
return count == 0
|
||
|
|
||
|
def allows_group_by_selected_pks_on_model(self, model):
|
||
|
if not self.allows_group_by_selected_pks:
|
||
|
return False
|
||
|
return model._meta.managed
|