mirror of
https://github.com/django/django.git
synced 2025-05-09 16:36:29 +00:00
Thanks to Adam Johnson, Carlton Gibson, Mariusz Felisiak, and Raphael Michel for mentoring this Google Summer of Code 2019 project and everyone else who helped with the patch. Special thanks to Mads Jensen, Nick Pope, and Simon Charette for extensive reviews. Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
338 lines
12 KiB
Python
338 lines
12 KiB
Python
from django.db import ProgrammingError
|
|
from django.utils.functional import cached_property
|
|
|
|
|
|
class BaseDatabaseFeatures:
|
|
gis_enabled = False
|
|
allows_group_by_pk = False
|
|
allows_group_by_selected_pks = False
|
|
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
|
|
# 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
|
|
|
|
# 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? MySQL says No.
|
|
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
|
|
|
|
# date_interval_sql can properly handle mixed Date/DateTime fields and timedeltas
|
|
supports_mixed_date_datetime_comparisons = True
|
|
|
|
# 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
|
|
|
|
# Can the backend introspect an AutoField, instead of an IntegerField?
|
|
can_introspect_autofield = False
|
|
|
|
# Can the backend introspect a BigIntegerField, instead of an IntegerField?
|
|
can_introspect_big_integer_field = True
|
|
|
|
# Can the backend introspect an BinaryField, instead of an TextField?
|
|
can_introspect_binary_field = True
|
|
|
|
# Can the backend introspect an DecimalField, instead of an FloatField?
|
|
can_introspect_decimal_field = True
|
|
|
|
# Can the backend introspect a DurationField, instead of a BigIntegerField?
|
|
can_introspect_duration_field = True
|
|
|
|
# Can the backend introspect an IPAddressField, instead of an CharField?
|
|
can_introspect_ip_address_field = False
|
|
|
|
# Can the backend introspect a PositiveIntegerField, instead of an IntegerField?
|
|
can_introspect_positive_integer_field = False
|
|
|
|
# Can the backend introspect a SmallIntegerField, instead of an IntegerField?
|
|
can_introspect_small_integer_field = False
|
|
|
|
# Can the backend introspect a TimeField, instead of a DateTimeField?
|
|
can_introspect_time_field = True
|
|
|
|
# Some backends may not be able to differentiate BigAutoField or
|
|
# SmallAutoField from other fields such as AutoField.
|
|
introspected_big_auto_field_type = 'BigAutoField'
|
|
introspected_small_auto_field_type = 'SmallAutoField'
|
|
|
|
# Some backends may not be able to differentiate BooleanField from other
|
|
# fields such as IntegerField.
|
|
introspected_boolean_field_type = 'BooleanField'
|
|
|
|
# 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
|
|
|
|
# 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
|
|
|
|
# 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 = True
|
|
|
|
# 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
|
|
|
|
# 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
|
|
|
|
# Does the backend support keyword parameters for cursor.callproc()?
|
|
supports_callproc_kwargs = False
|
|
|
|
# Convert CharField results from bytes to str in database functions.
|
|
db_functions_convert_bytes_to_str = False
|
|
|
|
# What formats does the backend EXPLAIN syntax support?
|
|
supported_explain_formats = set()
|
|
|
|
# Does DatabaseOperations.explain_query_prefix() raise ValueError if
|
|
# unknown kwargs are passed to QuerySet.explain()?
|
|
validates_explain_options = True
|
|
|
|
# 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 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 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 the SELECT clause?
|
|
supports_boolean_expr_in_select_clause = 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
|
|
|
|
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
|