From d436554861b9b818994276d7bf110bf03aa565f5 Mon Sep 17 00:00:00 2001
From: Nick Pope <nick@nickpope.me.uk>
Date: Fri, 28 Jan 2022 19:01:55 +0000
Subject: [PATCH] Fixed #33553 -- Used built-in math functions in SQLite 3.35+.

In SQLite 3.35+ some math functions are available built-in as long as
they are not disabled at compile time. We can introspect this and use
these built-in functions in preference to our slower implementations.
---
 django/db/backends/sqlite3/_functions.py | 39 +++++++++++++-----------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/django/db/backends/sqlite3/_functions.py b/django/db/backends/sqlite3/_functions.py
index f16d926100..49bd98cc5a 100644
--- a/django/db/backends/sqlite3/_functions.py
+++ b/django/db/backends/sqlite3/_functions.py
@@ -60,25 +60,10 @@ def register(connection):
     create_deterministic_function("django_timestamp_diff", 2, _sqlite_timestamp_diff)
     create_deterministic_function("django_format_dtdelta", 3, _sqlite_format_dtdelta)
     create_deterministic_function("regexp", 2, _sqlite_regexp)
-    create_deterministic_function("ACOS", 1, _sqlite_acos)
-    create_deterministic_function("ASIN", 1, _sqlite_asin)
-    create_deterministic_function("ATAN", 1, _sqlite_atan)
-    create_deterministic_function("ATAN2", 2, _sqlite_atan2)
     create_deterministic_function("BITXOR", 2, _sqlite_bitxor)
-    create_deterministic_function("CEILING", 1, _sqlite_ceiling)
-    create_deterministic_function("COS", 1, _sqlite_cos)
     create_deterministic_function("COT", 1, _sqlite_cot)
-    create_deterministic_function("DEGREES", 1, _sqlite_degrees)
-    create_deterministic_function("EXP", 1, _sqlite_exp)
-    create_deterministic_function("FLOOR", 1, _sqlite_floor)
-    create_deterministic_function("LN", 1, _sqlite_ln)
-    create_deterministic_function("LOG", 2, _sqlite_log)
     create_deterministic_function("LPAD", 3, _sqlite_lpad)
     create_deterministic_function("MD5", 1, _sqlite_md5)
-    create_deterministic_function("MOD", 2, _sqlite_mod)
-    create_deterministic_function("PI", 0, _sqlite_pi)
-    create_deterministic_function("POWER", 2, _sqlite_power)
-    create_deterministic_function("RADIANS", 1, _sqlite_radians)
     create_deterministic_function("REPEAT", 2, _sqlite_repeat)
     create_deterministic_function("REVERSE", 1, _sqlite_reverse)
     create_deterministic_function("RPAD", 3, _sqlite_rpad)
@@ -88,9 +73,6 @@ def register(connection):
     create_deterministic_function("SHA384", 1, _sqlite_sha384)
     create_deterministic_function("SHA512", 1, _sqlite_sha512)
     create_deterministic_function("SIGN", 1, _sqlite_sign)
-    create_deterministic_function("SIN", 1, _sqlite_sin)
-    create_deterministic_function("SQRT", 1, _sqlite_sqrt)
-    create_deterministic_function("TAN", 1, _sqlite_tan)
     # Don't use the built-in RANDOM() function because it returns a value
     # in the range [-1 * 2^63, 2^63 - 1] instead of [0, 1).
     connection.create_function("RAND", 0, random.random)
@@ -98,6 +80,27 @@ def register(connection):
     connection.create_aggregate("STDDEV_SAMP", 1, StdDevSamp)
     connection.create_aggregate("VAR_POP", 1, VarPop)
     connection.create_aggregate("VAR_SAMP", 1, VarSamp)
+    # Some math functions are enabled by default in SQLite 3.35+.
+    sql = "select sqlite_compileoption_used('ENABLE_MATH_FUNCTIONS')"
+    if not connection.execute(sql).fetchone()[0]:
+        create_deterministic_function("ACOS", 1, _sqlite_acos)
+        create_deterministic_function("ASIN", 1, _sqlite_asin)
+        create_deterministic_function("ATAN", 1, _sqlite_atan)
+        create_deterministic_function("ATAN2", 2, _sqlite_atan2)
+        create_deterministic_function("CEILING", 1, _sqlite_ceiling)
+        create_deterministic_function("COS", 1, _sqlite_cos)
+        create_deterministic_function("DEGREES", 1, _sqlite_degrees)
+        create_deterministic_function("EXP", 1, _sqlite_exp)
+        create_deterministic_function("FLOOR", 1, _sqlite_floor)
+        create_deterministic_function("LN", 1, _sqlite_ln)
+        create_deterministic_function("LOG", 2, _sqlite_log)
+        create_deterministic_function("MOD", 2, _sqlite_mod)
+        create_deterministic_function("PI", 0, _sqlite_pi)
+        create_deterministic_function("POWER", 2, _sqlite_power)
+        create_deterministic_function("RADIANS", 1, _sqlite_radians)
+        create_deterministic_function("SIN", 1, _sqlite_sin)
+        create_deterministic_function("SQRT", 1, _sqlite_sqrt)
+        create_deterministic_function("TAN", 1, _sqlite_tan)
 
 
 def _sqlite_datetime_parse(dt, tzname=None, conn_tzname=None):