mirror of
https://github.com/django/django.git
synced 2025-05-21 06:16:29 +00:00
Fixed #36143 -- Made max_query_params respect SQLITE_LIMIT_VARIABLE_NUMBER.
Co-authored-by: Xavier Frankline <xf.xavierfrank@gmail.com>
This commit is contained in:
parent
38660a612c
commit
358fd21c47
@ -1,4 +1,5 @@
|
|||||||
import operator
|
import operator
|
||||||
|
import sqlite3
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.backends.base.features import BaseDatabaseFeatures
|
from django.db.backends.base.features import BaseDatabaseFeatures
|
||||||
@ -13,7 +14,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||||||
test_db_allows_multiple_connections = False
|
test_db_allows_multiple_connections = False
|
||||||
supports_unspecified_pk = True
|
supports_unspecified_pk = True
|
||||||
supports_timezones = False
|
supports_timezones = False
|
||||||
max_query_params = 999
|
|
||||||
supports_transactions = True
|
supports_transactions = True
|
||||||
atomic_transactions = False
|
atomic_transactions = False
|
||||||
can_rollback_ddl = True
|
can_rollback_ddl = True
|
||||||
@ -140,6 +140,16 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||||||
"SmallAutoField": "AutoField",
|
"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
|
||||||
|
999 in versions < 3.32.0 or 32766 in newer versions) or lowered per
|
||||||
|
connection at run-time with setlimit(SQLITE_LIMIT_VARIABLE_NUMBER, N).
|
||||||
|
"""
|
||||||
|
return self.connection.connection.getlimit(sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def supports_json_field(self):
|
def supports_json_field(self):
|
||||||
with self.connection.cursor() as cursor:
|
with self.connection.cursor() as cursor:
|
||||||
|
@ -30,8 +30,8 @@ class DatabaseOperations(BaseDatabaseOperations):
|
|||||||
|
|
||||||
def bulk_batch_size(self, fields, objs):
|
def bulk_batch_size(self, fields, objs):
|
||||||
"""
|
"""
|
||||||
SQLite has a compile-time default (SQLITE_LIMIT_VARIABLE_NUMBER) of
|
SQLite has a variable limit defined by SQLITE_LIMIT_VARIABLE_NUMBER
|
||||||
999 variables per query.
|
(reflected in max_query_params).
|
||||||
|
|
||||||
If there's only a single field to insert, the limit is 500
|
If there's only a single field to insert, the limit is 500
|
||||||
(SQLITE_MAX_COMPOUND_SELECT).
|
(SQLITE_MAX_COMPOUND_SELECT).
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import sqlite3
|
||||||
from unittest import mock, skipUnless
|
from unittest import mock, skipUnless
|
||||||
|
|
||||||
from django.db import OperationalError, connection
|
from django.db import OperationalError, connection
|
||||||
@ -17,3 +18,14 @@ class FeaturesTests(TestCase):
|
|||||||
):
|
):
|
||||||
with self.assertRaisesMessage(OperationalError, msg):
|
with self.assertRaisesMessage(OperationalError, msg):
|
||||||
connection.features.supports_json_field
|
connection.features.supports_json_field
|
||||||
|
|
||||||
|
def test_max_query_params_respects_variable_limit(self):
|
||||||
|
limit_name = sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER
|
||||||
|
current_limit = connection.features.max_query_params
|
||||||
|
new_limit = min(42, current_limit)
|
||||||
|
try:
|
||||||
|
connection.connection.setlimit(limit_name, new_limit)
|
||||||
|
self.assertEqual(connection.features.max_query_params, new_limit)
|
||||||
|
finally:
|
||||||
|
connection.connection.setlimit(limit_name, current_limit)
|
||||||
|
self.assertEqual(connection.features.max_query_params, current_limit)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import sqlite3
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from django.core.management.color import no_style
|
from django.core.management.color import no_style
|
||||||
@ -108,3 +109,32 @@ class SQLiteOperationsTests(TestCase):
|
|||||||
),
|
),
|
||||||
connection.features.max_query_params // 3,
|
connection.features.max_query_params // 3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_bulk_batch_size_respects_variable_limit(self):
|
||||||
|
first_name_field = Person._meta.get_field("first_name")
|
||||||
|
last_name_field = Person._meta.get_field("last_name")
|
||||||
|
limit_name = sqlite3.SQLITE_LIMIT_VARIABLE_NUMBER
|
||||||
|
current_limit = connection.features.max_query_params
|
||||||
|
self.assertEqual(
|
||||||
|
connection.ops.bulk_batch_size(
|
||||||
|
[first_name_field, last_name_field], [Person()]
|
||||||
|
),
|
||||||
|
current_limit // 2,
|
||||||
|
)
|
||||||
|
new_limit = min(42, current_limit)
|
||||||
|
try:
|
||||||
|
connection.connection.setlimit(limit_name, new_limit)
|
||||||
|
self.assertEqual(
|
||||||
|
connection.ops.bulk_batch_size(
|
||||||
|
[first_name_field, last_name_field], [Person()]
|
||||||
|
),
|
||||||
|
new_limit // 2,
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
connection.connection.setlimit(limit_name, current_limit)
|
||||||
|
self.assertEqual(
|
||||||
|
connection.ops.bulk_batch_size(
|
||||||
|
[first_name_field, last_name_field], [Person()]
|
||||||
|
),
|
||||||
|
current_limit // 2,
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user