This commit is contained in:
2025-05-22 20:25:38 +02:00
parent 09f6750c2b
commit ce03fbf12f
529 changed files with 3353 additions and 3312 deletions

View File

@@ -59,4 +59,5 @@ __all__ = (
"VARCHAR2",
"NVARCHAR2",
"ROWID",
"REAL",
)

View File

@@ -1241,6 +1241,9 @@ class OracleCompiler(compiler.SQLCompiler):
self.render_literal_value(flags, sqltypes.STRINGTYPE),
)
def visit_aggregate_strings_func(self, fn, **kw):
return "LISTAGG%s" % self.function_argspec(fn, **kw)
class OracleDDLCompiler(compiler.DDLCompiler):
def define_constraint_cascades(self, constraint):
@@ -1315,8 +1318,9 @@ class OracleDDLCompiler(compiler.DDLCompiler):
text = text.replace("NO MINVALUE", "NOMINVALUE")
text = text.replace("NO MAXVALUE", "NOMAXVALUE")
text = text.replace("NO CYCLE", "NOCYCLE")
text = text.replace("NO ORDER", "NOORDER")
return text
if identity_options.order is not None:
text += " ORDER" if identity_options.order else " NOORDER"
return text.strip()
def visit_computed_column(self, generated, **kw):
text = "GENERATED ALWAYS AS (%s)" % self.sql_compiler.process(

View File

@@ -978,8 +978,8 @@ class OracleDialect_cx_oracle(OracleDialect):
driver = "cx_oracle"
colspecs = OracleDialect.colspecs
colspecs.update(
colspecs = util.update_copy(
OracleDialect.colspecs,
{
sqltypes.TIMESTAMP: _CXOracleTIMESTAMP,
sqltypes.Numeric: _OracleNumeric,
@@ -1006,7 +1006,7 @@ class OracleDialect_cx_oracle(OracleDialect):
sqltypes.Uuid: _OracleUUID,
oracle.NCLOB: _OracleUnicodeTextNCLOB,
oracle.ROWID: _OracleRowid,
}
},
)
execute_sequence_format = list
@@ -1088,9 +1088,9 @@ class OracleDialect_cx_oracle(OracleDialect):
int(x) for x in m.group(1, 2, 3) if x is not None
)
self.cx_oracle_ver = version
if self.cx_oracle_ver < (7,) and self.cx_oracle_ver > (0, 0, 0):
if self.cx_oracle_ver < (8,) and self.cx_oracle_ver > (0, 0, 0):
raise exc.InvalidRequestError(
"cx_Oracle version 7 and above are supported"
"cx_Oracle version 8 and above are supported"
)
@classmethod

View File

@@ -4,12 +4,22 @@
# This module is part of SQLAlchemy and is released under
# the MIT License: https://www.opensource.org/licenses/mit-license.php
# mypy: ignore-errors
from __future__ import annotations
import datetime as dt
from typing import Optional
from typing import Type
from typing import TYPE_CHECKING
from ... import exc
from ...sql import sqltypes
from ...types import NVARCHAR
from ...types import VARCHAR
if TYPE_CHECKING:
from ...engine.interfaces import Dialect
from ...sql.type_api import _LiteralProcessorType
class RAW(sqltypes._Binary):
__visit_name__ = "RAW"
@@ -116,38 +126,36 @@ class LONG(sqltypes.Text):
class _OracleDateLiteralRender:
def _literal_processor_datetime(self, dialect):
def process(value):
if value is not None:
if getattr(value, "microsecond", None):
value = (
f"""TO_TIMESTAMP"""
f"""('{value.isoformat().replace("T", " ")}', """
"""'YYYY-MM-DD HH24:MI:SS.FF')"""
)
else:
value = (
f"""TO_DATE"""
f"""('{value.isoformat().replace("T", " ")}', """
"""'YYYY-MM-DD HH24:MI:SS')"""
)
if getattr(value, "microsecond", None):
value = (
f"""TO_TIMESTAMP"""
f"""('{value.isoformat().replace("T", " ")}', """
"""'YYYY-MM-DD HH24:MI:SS.FF')"""
)
else:
value = (
f"""TO_DATE"""
f"""('{value.isoformat().replace("T", " ")}', """
"""'YYYY-MM-DD HH24:MI:SS')"""
)
return value
return process
def _literal_processor_date(self, dialect):
def process(value):
if value is not None:
if getattr(value, "microsecond", None):
value = (
f"""TO_TIMESTAMP"""
f"""('{value.isoformat().split("T")[0]}', """
"""'YYYY-MM-DD')"""
)
else:
value = (
f"""TO_DATE"""
f"""('{value.isoformat().split("T")[0]}', """
"""'YYYY-MM-DD')"""
)
if getattr(value, "microsecond", None):
value = (
f"""TO_TIMESTAMP"""
f"""('{value.isoformat().split("T")[0]}', """
"""'YYYY-MM-DD')"""
)
else:
value = (
f"""TO_DATE"""
f"""('{value.isoformat().split("T")[0]}', """
"""'YYYY-MM-DD')"""
)
return value
return process
@@ -203,6 +211,15 @@ class INTERVAL(sqltypes.NativeForEmulated, sqltypes._AbstractInterval):
second_precision=interval.second_precision,
)
@classmethod
def adapt_emulated_to_native(
cls, interval: sqltypes.Interval, **kw # type: ignore[override]
):
return INTERVAL(
day_precision=interval.day_precision,
second_precision=interval.second_precision,
)
@property
def _type_affinity(self):
return sqltypes.Interval
@@ -214,6 +231,18 @@ class INTERVAL(sqltypes.NativeForEmulated, sqltypes._AbstractInterval):
day_precision=self.day_precision,
)
@property
def python_type(self) -> Type[dt.timedelta]:
return dt.timedelta
def literal_processor(
self, dialect: Dialect
) -> Optional[_LiteralProcessorType[dt.timedelta]]:
def process(value: dt.timedelta) -> str:
return f"NUMTODSINTERVAL({value.total_seconds()}, 'SECOND')"
return process
class TIMESTAMP(sqltypes.TIMESTAMP):
"""Oracle implementation of ``TIMESTAMP``, which supports additional