summaryrefslogtreecommitdiff
path: root/django/db/backends/sqlite3
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2023-08-04 06:35:13 +0200
committerGitHub <noreply@github.com>2023-08-04 06:35:13 +0200
commit2b582387d51c44fa928351ca55f05fc8b8d2986e (patch)
tree79eb0423530ab2a9ce8dbdbd20431bab073a5b71 /django/db/backends/sqlite3
parentf46a6b2816819ed12d4d0150c99d66920070ca15 (diff)
Fixed #34760 -- Dropped support for SQLite < 3.27.
Diffstat (limited to 'django/db/backends/sqlite3')
-rw-r--r--django/db/backends/sqlite3/base.py2
-rw-r--r--django/db/backends/sqlite3/features.py23
-rw-r--r--django/db/backends/sqlite3/schema.py104
3 files changed, 6 insertions, 123 deletions
diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py
index a3a382a56b..08de0bad5a 100644
--- a/django/db/backends/sqlite3/base.py
+++ b/django/db/backends/sqlite3/base.py
@@ -182,7 +182,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
conn.execute("PRAGMA foreign_keys = ON")
# The macOS bundled SQLite defaults legacy_alter_table ON, which
- # prevents atomic table renames (feature supports_atomic_references_rename)
+ # prevents atomic table renames.
conn.execute("PRAGMA legacy_alter_table = OFF")
return conn
diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py
index f471b72cb2..3ae84f2646 100644
--- a/django/db/backends/sqlite3/features.py
+++ b/django/db/backends/sqlite3/features.py
@@ -9,7 +9,7 @@ from .base import Database
class DatabaseFeatures(BaseDatabaseFeatures):
- minimum_database_version = (3, 21)
+ minimum_database_version = (3, 27)
test_db_allows_multiple_connections = False
supports_unspecified_pk = True
supports_timezones = False
@@ -26,13 +26,11 @@ class DatabaseFeatures(BaseDatabaseFeatures):
time_cast_precision = 3
can_release_savepoints = True
has_case_insensitive_like = True
- # Is "ALTER TABLE ... RENAME COLUMN" supported?
- can_alter_table_rename_column = Database.sqlite_version_info >= (3, 25, 0)
# Is "ALTER TABLE ... DROP COLUMN" supported?
can_alter_table_drop_column = Database.sqlite_version_info >= (3, 35, 5)
supports_parentheses_in_compound = False
can_defer_constraint_checks = True
- supports_over_clause = Database.sqlite_version_info >= (3, 25, 0)
+ supports_over_clause = True
supports_frame_range_fixed_distance = Database.sqlite_version_info >= (3, 28, 0)
supports_aggregate_filter_clause = Database.sqlite_version_info >= (3, 30, 1)
supports_order_by_nulls_modifier = Database.sqlite_version_info >= (3, 30, 0)
@@ -40,8 +38,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
requires_compound_order_by_subquery = Database.sqlite_version_info < (3, 30)
order_by_nulls_first = True
supports_json_field_contains = False
- supports_update_conflicts = Database.sqlite_version_info >= (3, 24, 0)
- supports_update_conflicts_with_target = supports_update_conflicts
+ supports_update_conflicts = True
+ supports_update_conflicts_with_target = True
test_collations = {
"ci": "nocase",
"cs": "binary",
@@ -88,15 +86,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
"test_integer_with_negative_precision",
},
}
- if Database.sqlite_version_info < (3, 27):
- skips.update(
- {
- "Nondeterministic failure on SQLite < 3.27.": {
- "expressions_window.tests.WindowFunctionTests."
- "test_subquery_row_range_rank",
- },
- }
- )
if self.connection.is_in_memory_db():
skips.update(
{
@@ -132,10 +121,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
return skips
@cached_property
- def supports_atomic_references_rename(self):
- return Database.sqlite_version_info >= (3, 26, 0)
-
- @cached_property
def introspected_field_types(self):
return {
**super().introspected_field_types,
diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py
index 46ba07092d..ec128fd733 100644
--- a/django/db/backends/sqlite3/schema.py
+++ b/django/db/backends/sqlite3/schema.py
@@ -7,7 +7,6 @@ from django.db.backends.base.schema import BaseDatabaseSchemaEditor
from django.db.backends.ddl_references import Statement
from django.db.backends.utils import strip_quotes
from django.db.models import NOT_PROVIDED, UniqueConstraint
-from django.db.transaction import atomic
class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
@@ -73,105 +72,6 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
def prepare_default(self, value):
return self.quote_value(value)
- def _is_referenced_by_fk_constraint(
- self, table_name, column_name=None, ignore_self=False
- ):
- """
- Return whether or not the provided table name is referenced by another
- one. If `column_name` is specified, only references pointing to that
- column are considered. If `ignore_self` is True, self-referential
- constraints are ignored.
- """
- with self.connection.cursor() as cursor:
- for other_table in self.connection.introspection.get_table_list(cursor):
- if ignore_self and other_table.name == table_name:
- continue
- relations = self.connection.introspection.get_relations(
- cursor, other_table.name
- )
- for constraint_column, constraint_table in relations.values():
- if constraint_table == table_name and (
- column_name is None or constraint_column == column_name
- ):
- return True
- return False
-
- def alter_db_table(
- self, model, old_db_table, new_db_table, disable_constraints=True
- ):
- if (
- not self.connection.features.supports_atomic_references_rename
- and disable_constraints
- and self._is_referenced_by_fk_constraint(old_db_table)
- ):
- if self.connection.in_atomic_block:
- raise NotSupportedError(
- (
- "Renaming the %r table while in a transaction is not "
- "supported on SQLite < 3.26 because it would break referential "
- "integrity. Try adding `atomic = False` to the Migration class."
- )
- % old_db_table
- )
- self.connection.enable_constraint_checking()
- super().alter_db_table(model, old_db_table, new_db_table)
- self.connection.disable_constraint_checking()
- else:
- super().alter_db_table(model, old_db_table, new_db_table)
-
- def alter_field(self, model, old_field, new_field, strict=False):
- if not self._field_should_be_altered(old_field, new_field):
- return
- old_field_name = old_field.name
- table_name = model._meta.db_table
- _, old_column_name = old_field.get_attname_column()
- if (
- new_field.name != old_field_name
- and not self.connection.features.supports_atomic_references_rename
- and self._is_referenced_by_fk_constraint(
- table_name, old_column_name, ignore_self=True
- )
- ):
- if self.connection.in_atomic_block:
- raise NotSupportedError(
- (
- "Renaming the %r.%r column while in a transaction is not "
- "supported on SQLite < 3.26 because it would break referential "
- "integrity. Try adding `atomic = False` to the Migration class."
- )
- % (model._meta.db_table, old_field_name)
- )
- with atomic(self.connection.alias):
- super().alter_field(model, old_field, new_field, strict=strict)
- # Follow SQLite's documented procedure for performing changes
- # that don't affect the on-disk content.
- # https://sqlite.org/lang_altertable.html#otheralter
- with self.connection.cursor() as cursor:
- schema_version = cursor.execute("PRAGMA schema_version").fetchone()[
- 0
- ]
- cursor.execute("PRAGMA writable_schema = 1")
- references_template = ' REFERENCES "%s" ("%%s") ' % table_name
- new_column_name = new_field.get_attname_column()[1]
- search = references_template % old_column_name
- replacement = references_template % new_column_name
- cursor.execute(
- "UPDATE sqlite_master SET sql = replace(sql, %s, %s)",
- (search, replacement),
- )
- cursor.execute("PRAGMA schema_version = %d" % (schema_version + 1))
- cursor.execute("PRAGMA writable_schema = 0")
- # The integrity check will raise an exception and rollback
- # the transaction if the sqlite_master updates corrupt the
- # database.
- cursor.execute("PRAGMA integrity_check")
- # Perform a VACUUM to refresh the database representation from
- # the sqlite_master table.
- with self.connection.cursor() as cursor:
- cursor.execute("VACUUM")
- else:
- super().alter_field(model, old_field, new_field, strict=strict)
-
def _remake_table(
self, model, create_field=None, delete_field=None, alter_fields=None
):
@@ -358,7 +258,6 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
new_model,
new_model._meta.db_table,
model._meta.db_table,
- disable_constraints=False,
)
# Run deferred SQL on correct table
@@ -458,8 +357,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
# Use "ALTER TABLE ... RENAME COLUMN" if only the column name
# changed and there aren't any constraints.
if (
- self.connection.features.can_alter_table_rename_column
- and old_field.column != new_field.column
+ old_field.column != new_field.column
and self.column_sql(model, old_field) == self.column_sql(model, new_field)
and not (
old_field.remote_field