Nick Pope 2023-12-12 16:07:31 +00:00 committed by Mariusz Felisiak
parent a816efe238
commit c72001644f
4 changed files with 16 additions and 7 deletions

View File

@ -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
@ -159,9 +158,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
@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
@ -183,3 +183,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
@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"

View File

@ -54,7 +54,7 @@ BEGIN
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;
@ -527,6 +527,7 @@ END;
"column": column,
"table_name": strip_quotes(table),
"column_name": strip_quotes(column),
"suffix": self.connection.features.bare_select_suffix,
}
sql.append(query)
return sql
@ -550,6 +551,7 @@ END;
"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
@ -683,7 +685,8 @@ END;
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.

View File

@ -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,

View File

@ -43,8 +43,9 @@ class Tests(TestCase):
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)