Skip to content

cx_Oracle Integer Overflow/Underflow with SQLAlchemy 1.2.x #4457

@mpeleshenko

Description

@mpeleshenko

I'm seeing integer overflow/underflow for NUMBER types in SQLAlchemy 1.2.x, but not in 1.1.18 with cx_Oracle 7.0.0.

Test Script
import cx_Oracle
import sqlalchemy
import sys

oracle_dialect = 'oracle'
oracle_driver = 'cx_oracle'
oracle_username = ''
oracle_password = ''
oracle_host = ''
oracle_port = 0
oracle_database = ''
oracle_dsn = '{host}:{port}/{database}'.format(host=oracle_host, port=oracle_port, database=oracle_database)

oracle_url = '{dialect}+{driver}://{username}:{password}@{dsn}'.format(
    dialect=oracle_dialect,
    driver=oracle_driver,
    username=oracle_username,
    password=oracle_password,
    dsn=oracle_dsn,
)

query_cases = [
    ('Max 32-bit Number', 'SELECT CAST(2147483647 AS NUMBER(19,0)) FROM dual'),
    ('Min 32-bit Number', 'SELECT CAST(-2147483648 AS NUMBER(19,0)) FROM dual'),
    ('32-bit Integer Overflow', 'SELECT CAST(2147483648 AS NUMBER(19,0)) FROM dual'),
    ('32-bit Integer Underflow', 'SELECT CAST(-2147483649 AS NUMBER(19,0)) FROM dual'),
    ('Max Number with Precision 19', 'SELECT CAST(9999999999999999999 AS NUMBER(19,0)) FROM dual'),
    ('Min Number with Precision 19', 'SELECT CAST(-9999999999999999999 AS NUMBER(19,0)) FROM dual'),
]

cx_oracle_connection = cx_Oracle.connect(
    oracle_username,
    oracle_password,
    oracle_dsn,
)
sqlalchemy_engine = sqlalchemy.create_engine(oracle_url)

print('Python Version:', sys.version)
print('SQLAlchemy Version:', sqlalchemy.__version__)
print('cx_Oracle Version:', cx_Oracle.__version__)

with cx_oracle_connection.cursor() as cursor:
    oracle_server_version = cursor.execute('SELECT banner FROM v$version').fetchall()
    print('Oracle Server Version:')
    for v in oracle_server_version:
        print('\t{}'.format(v[0]))

print('Oracle Client Version:', '.'.join(str(x) for x in cx_Oracle.clientversion()))

print('-' * 50)
print('Test Cases:')
for query_case, query in query_cases:
    cx_oracle_msg = '{} (cx_Oracle): '.format(query_case)
    with cx_oracle_connection.cursor() as cursor:
        try:
            cx_oracle_result = cursor.execute(query).fetchall()
        except Exception as e:
            cx_oracle_result = e
        else:
            cx_oracle_result = cx_oracle_result[0][0]
    print(cx_oracle_msg + str(cx_oracle_result))

    sqlalchemy_msg = '{} (SQLAlchemy): '.format(query_case)
    try:
        sqlalchemy_result = sqlalchemy_engine.execute(query).fetchall()
    except Exception as e:
        sqlalchemy_result = e
    else:
        sqlalchemy_result = sqlalchemy_result[0][0]
    print(sqlalchemy_msg + str(sqlalchemy_result))

    if cx_oracle_result != sqlalchemy_result:
        print('##### SQLALCHEMY DOES NOT MATCH CX_ORACLE FOR {}'.format(query_case))

Script Output with SQLAlchemy 1.1.18

Python Version: 3.5.6 |Anaconda, Inc.| (default, Aug 26 2018, 16:05:27) [MSC v.1900 64 bit (AMD64)]
SQLAlchemy Version: 1.1.18
cx_Oracle Version: 7.0.0
Oracle Server Version:
	Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
	PL/SQL Release 12.1.0.2.0 - Production
	CORE	12.1.0.2.0	Production
	TNS for Linux: Version 12.1.0.2.0 - Production
	NLSRTL Version 12.1.0.2.0 - Production
Oracle Client Version: 12.1.0.2.0
--------------------------------------------------
Test Cases:
Max 32-bit Number (cx_Oracle): 2147483647
Max 32-bit Number (SQLAlchemy): 2147483647
Min 32-bit Number (cx_Oracle): -2147483648
Min 32-bit Number (SQLAlchemy): -2147483648
32-bit Integer Overflow (cx_Oracle): 2147483648
32-bit Integer Overflow (SQLAlchemy): 2147483648
32-bit Integer Underflow (cx_Oracle): -2147483649
32-bit Integer Underflow (SQLAlchemy): -2147483649
Max Number with Precision 19 (cx_Oracle): 9999999999999999999
Max Number with Precision 19 (SQLAlchemy): 9999999999999999999
Min Number with Precision 19 (cx_Oracle): -9999999999999999999
Min Number with Precision 19 (SQLAlchemy): -9999999999999999999

Script Output with SQLAlchemy 1.2.16

Python Version: 3.5.6 |Anaconda, Inc.| (default, Aug 26 2018, 16:05:27) [MSC v.1900 64 bit (AMD64)]
SQLAlchemy Version: 1.2.16
cx_Oracle Version: 7.0.0
Oracle Server Version:
	Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
	PL/SQL Release 12.1.0.2.0 - Production
	CORE	12.1.0.2.0	Production
	TNS for Linux: Version 12.1.0.2.0 - Production
	NLSRTL Version 12.1.0.2.0 - Production
Oracle Client Version: 12.1.0.2.0
--------------------------------------------------
Test Cases:
Max 32-bit Number (cx_Oracle): 2147483647
Max 32-bit Number (SQLAlchemy): 2147483647
Min 32-bit Number (cx_Oracle): -2147483648
Min 32-bit Number (SQLAlchemy): -2147483648
32-bit Integer Overflow (cx_Oracle): 2147483648
32-bit Integer Overflow (SQLAlchemy): -2147483648
##### SQLALCHEMY DOES NOT MATCH CX_ORACLE FOR 32-bit Integer Overflow
32-bit Integer Underflow (cx_Oracle): -2147483649
32-bit Integer Underflow (SQLAlchemy): 2147483647
##### SQLALCHEMY DOES NOT MATCH CX_ORACLE FOR 32-bit Integer Underflow
Max Number with Precision 19 (cx_Oracle): 9999999999999999999
Max Number with Precision 19 (SQLAlchemy): (cx_Oracle.DatabaseError) ORA-01455: converting column overflows integer datatype (Background on this error at: http://sqlalche.me/e/4xp6)
##### SQLALCHEMY DOES NOT MATCH CX_ORACLE FOR Max Number with Precision 19
Min Number with Precision 19 (cx_Oracle): -9999999999999999999
Min Number with Precision 19 (SQLAlchemy): (cx_Oracle.DatabaseError) ORA-01455: converting column overflows integer datatype (Background on this error at: http://sqlalche.me/e/4xp6)
##### SQLALCHEMY DOES NOT MATCH CX_ORACLE FOR Min Number with Precision 19

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingoracle

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions