Skip to content

Commit

Permalink
Updated DatabaseFeatures.bare_select_suffix on Oracle 23c.
Browse files Browse the repository at this point in the history
  • Loading branch information
ngnpope authored and felixxm committed Jan 1, 2024
1 parent a816efe commit c720016
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 7 deletions.
8 changes: 6 additions & 2 deletions django/db/backends/oracle/features.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
requires_literal_defaults = True
supports_default_keyword_in_bulk_insert = False
closed_cursor_error_class = InterfaceError
bare_select_suffix = " FROM DUAL"
# Select for update with limit can be achieved on Oracle, but not with the
# current backend.
supports_select_for_update_with_limit = False
Expand Down Expand Up @@ -159,9 +158,10 @@ def test_collations(self):

@cached_property
def supports_collation_on_charfield(self):
sql = "SELECT CAST('a' AS VARCHAR2(4001))" + self.bare_select_suffix
with self.connection.cursor() as cursor:
try:
cursor.execute("SELECT CAST('a' AS VARCHAR2(4001)) FROM dual")
cursor.execute(sql)
except DatabaseError as e:
if e.args[0].code == 910:
return False
Expand All @@ -183,3 +183,7 @@ def supports_boolean_expr_in_select_clause(self):
@cached_property
def supports_aggregation_over_interval_types(self):
return self.connection.oracle_version >= (23,)

@cached_property
def bare_select_suffix(self):
return "" if self.connection.oracle_version >= (23,) else " FROM DUAL"
7 changes: 5 additions & 2 deletions django/db/backends/oracle/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class DatabaseOperations(BaseDatabaseOperations):
SELECT NVL(last_number - cache_size, 0) INTO seq_value FROM user_sequences
WHERE sequence_name = seq_name;
WHILE table_value > seq_value LOOP
EXECUTE IMMEDIATE 'SELECT "'||seq_name||'".nextval FROM DUAL'
EXECUTE IMMEDIATE 'SELECT "'||seq_name||'".nextval%(suffix)s'
INTO seq_value;
END LOOP;
END;
Expand Down Expand Up @@ -527,6 +527,7 @@ def sequence_reset_by_name_sql(self, style, sequences):
"column": column,
"table_name": strip_quotes(table),
"column_name": strip_quotes(column),
"suffix": self.connection.features.bare_select_suffix,
}
sql.append(query)
return sql
Expand All @@ -550,6 +551,7 @@ def sequence_reset_sql(self, style, model_list):
"column": column,
"table_name": strip_quotes(table),
"column_name": strip_quotes(column),
"suffix": self.connection.features.bare_select_suffix,
}
)
# Only one AutoField is allowed per model, so don't
Expand Down Expand Up @@ -683,7 +685,8 @@ def bulk_insert_sql(self, fields, placeholder_rows):
if not query:
placeholder = "%s col_%s" % (placeholder, i)
select.append(placeholder)
query.append("SELECT %s FROM DUAL" % ", ".join(select))
suffix = self.connection.features.bare_select_suffix
query.append(f"SELECT %s{suffix}" % ", ".join(select))
# Bulk insert to tables with Oracle identity columns causes Oracle to
# add sequence.nextval to it. Sequence.nextval cannot be used with the
# UNION operator. To prevent incorrect SQL, move UNION to a subquery.
Expand Down
5 changes: 3 additions & 2 deletions django/db/models/functions/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,14 @@ class Reverse(Transform):
def as_oracle(self, compiler, connection, **extra_context):
# REVERSE in Oracle is undocumented and doesn't support multi-byte
# strings. Use a special subquery instead.
suffix = connection.features.bare_select_suffix
sql, params = super().as_sql(
compiler,
connection,
template=(
"(SELECT LISTAGG(s) WITHIN GROUP (ORDER BY n DESC) FROM "
"(SELECT LEVEL n, SUBSTR(%(expressions)s, LEVEL, 1) s "
"FROM DUAL CONNECT BY LEVEL <= LENGTH(%(expressions)s)) "
f"(SELECT LEVEL n, SUBSTR(%(expressions)s, LEVEL, 1) s{suffix} "
"CONNECT BY LEVEL <= LENGTH(%(expressions)s)) "
"GROUP BY %(expressions)s)"
),
**extra_context,
Expand Down
3 changes: 2 additions & 1 deletion tests/backends/oracle/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ def test_order_of_nls_parameters(self):
An 'almost right' datetime works with configured NLS parameters
(#18465).
"""
suffix = connection.features.bare_select_suffix
with connection.cursor() as cursor:
query = "select 1 from dual where '1936-12-29 00:00' < sysdate"
query = f"SELECT 1{suffix} WHERE '1936-12-29 00:00' < SYSDATE"
# The query succeeds without errors - pre #18465 this
# wasn't the case.
cursor.execute(query)
Expand Down

0 comments on commit c720016

Please sign in to comment.