From 32b2b31da2017fae8fcb759a52ad3d7081dec933 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 31 Oct 2022 15:09:34 -0400 Subject: use simple decimal query to detect decimal char Fixed issue where the ``nls_session_parameters`` view queried on first connect in order to get the default decimal point character may not be available depending on Oracle connection modes, and would therefore raise an error. The approach to detecting decimal char has been simplified to test a decimal value directly, instead of reading system views, which works on any backend / driver. Fixes: #8744 Change-Id: I39825131c13513798863197d0c180dd5a18b32dc --- lib/sqlalchemy/dialects/oracle/cx_oracle.py | 31 +++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'lib/sqlalchemy') diff --git a/lib/sqlalchemy/dialects/oracle/cx_oracle.py b/lib/sqlalchemy/dialects/oracle/cx_oracle.py index 24262c181..5a0c0e160 100644 --- a/lib/sqlalchemy/dialects/oracle/cx_oracle.py +++ b/lib/sqlalchemy/dialects/oracle/cx_oracle.py @@ -1133,10 +1133,33 @@ class OracleDialect_cx_oracle(OracleDialect): # NLS_TERRITORY or formatting behavior of the DB, we opt # to just look at it - self._decimal_char = connection.exec_driver_sql( - "select value from nls_session_parameters " - "where parameter = 'NLS_NUMERIC_CHARACTERS'" - ).scalar()[0] + dbapi_connection = connection.connection + + with dbapi_connection.cursor() as cursor: + # issue #8744 + # nls_session_parameters is not available in some Oracle + # modes like "mount mode". But then, v$nls_parameters is not + # available if the connection doesn't have SYSDBA priv. + # + # simplify the whole thing and just use the method that we were + # doing in the test suite already, selecting a number + + def output_type_handler( + cursor, name, defaultType, size, precision, scale + ): + return cursor.var( + self.dbapi.STRING, 255, arraysize=cursor.arraysize + ) + + cursor.outputtypehandler = output_type_handler + cursor.execute("SELECT 1.1 FROM DUAL") + value = cursor.fetchone()[0] + + decimal_char = value.lstrip("0")[1] + assert not decimal_char[0].isdigit() + + self._decimal_char = decimal_char + if self._decimal_char != ".": _detect_decimal = self._detect_decimal _to_decimal = self._to_decimal -- cgit v1.2.1