Skip to content

Commit

Permalink
Fixed #24018 -- Allowed setting pragma options on SQLite.
Browse files Browse the repository at this point in the history
  • Loading branch information
linville authored and felixxm committed Feb 16, 2024
1 parent 66e47ac commit 7a05b8a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ people who have submitted patches, reported bugs, added translations, helped
answer newbie questions, and generally made Django that much better:

Aaron Cannon <[email protected]>
Aaron Linville <[email protected]>
Aaron Swartz <http://www.aaronsw.com/>
Aaron T. Myers <[email protected]>
Abeer Upadhyay <[email protected]>
Expand Down
6 changes: 6 additions & 0 deletions django/db/backends/sqlite3/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ def get_connection_params(self):
f"{allowed_transaction_modes}, or None."
)
self.transaction_mode = transaction_mode.upper() if transaction_mode else None

init_command = kwargs.pop("init_command", "")
self.init_commands = init_command.split(";")
return kwargs

def get_database_version(self):
Expand All @@ -201,6 +204,9 @@ def get_new_connection(self, conn_params):
# The macOS bundled SQLite defaults legacy_alter_table ON, which
# prevents atomic table renames.
conn.execute("PRAGMA legacy_alter_table = OFF")
for init_command in self.init_commands:
if init_command := init_command.strip():
conn.execute(init_command)
return conn

def create_cursor(self, name=None):
Expand Down
24 changes: 24 additions & 0 deletions docs/ref/databases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,30 @@ To enable the JSON1 extension you can follow the instruction on
.. _JSON1 extension: https://www.sqlite.org/json1.html
.. _the wiki page: https://code.djangoproject.com/wiki/JSON1Extension

.. _sqlite-init-command:

Setting pragma options
----------------------

.. versionadded:: 5.1

`Pragma options`_ can be set upon connection by using the ``init_command`` in
the :setting:`OPTIONS` part of your database configuration in
:setting:`DATABASES`. The example below shows how to enable extra durability of
synchronous writes and change the ``cache_size``::

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
# ...
"OPTIONS": {
"init_command": "PRAGMA synchronous=3; PRAGMA cache_size=2000;",
},
}
}

.. _Pragma options: https://www.sqlite.org/pragma.html

.. _oracle-notes:

Oracle notes
Expand Down
7 changes: 7 additions & 0 deletions docs/releases/5.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ CSRF

* ...

Database backends
~~~~~~~~~~~~~~~~~

* ``"init_command"`` option is now supported in :setting:`OPTIONS` on SQLite
to allow specifying :ref:`pragma options <sqlite-init-command>` to set upon
connection.

Decorators
~~~~~~~~~~

Expand Down
1 change: 1 addition & 0 deletions docs/spelling_wordlist
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ postfix
postgis
postgres
postgresql
pragma
pre
precisions
precomputation
Expand Down
23 changes: 23 additions & 0 deletions tests/backends/sqlite/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,29 @@ def test_check_database_version_supported(self, mocked_get_database_version):
connection.check_database_version_supported()
self.assertTrue(mocked_get_database_version.called)

def test_init_command(self):
settings_dict = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
"OPTIONS": {
"init_command": "PRAGMA synchronous=3; PRAGMA cache_size=2000;",
},
}
}
connections = ConnectionHandler(settings_dict)
connections["default"].ensure_connection()
try:
with connections["default"].cursor() as cursor:
cursor.execute("PRAGMA synchronous")
value = cursor.fetchone()[0]
self.assertEqual(value, 3)
cursor.execute("PRAGMA cache_size")
value = cursor.fetchone()[0]
self.assertEqual(value, 2000)
finally:
connections["default"].close()


@unittest.skipUnless(connection.vendor == "sqlite", "SQLite tests")
@isolate_apps("backends")
Expand Down

0 comments on commit 7a05b8a

Please sign in to comment.