-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test ExceptionTest_exasol_pyodbc::()::test_integrity_error fails #42
Comments
Any updates on this issue? |
@andrii-kravchenko-by - no change on this one and currently no priority to get this fixed. If you are willing and able to help out this might be a good issue to start with. |
The analysis of this issue has shown, that depending on the kind of insert statement, the underlying odbc driver parts do not seem to propagate the sql-error, which causes this test to fail. DetailsValidated withDATABASE VERSIONEXASOL DB 7.1.6 EXASOL ODBC DRIVERlibexasolodbc 7.0.11 (latest 7.0.x) PYTHON VERSIONPython 3.9.7 PYTHON ODBC VERSIONName: pyodbc Steps to reproduce:
Attention: replace python regression.py --odbc-log --system-info prepared-insert driver/libexaodbc-uo2214lv1.so Expected behaviour:
python regression.py --odbc-log --system-info insert driver/libexaodbc-uo2214lv1.so Observed behaviour:
TODO's
Attachments
import argparse
import os
import sys
from contextlib import contextmanager
from pathlib import Path
from platform import platform
from subprocess import run
from tempfile import TemporaryDirectory
from textwrap import dedent
from pyodbc import connect
ODBCINST_INI_TEMPLATE = dedent(
"""
[ODBC]
Trace = {trace}
TraceFile = {trace_file}
[EXAODBC]
#Driver location will be appended in build environment:
DRIVER={driver}
"""
)
@contextmanager
def environment(env_vars):
_env = os.environ.copy()
os.environ.update(env_vars)
yield os.environ
os.environ.clear()
os.environ.update(_env)
@contextmanager
def temporary_odbc_config(config):
with TemporaryDirectory() as tmp_dir:
tmp_dir = Path(tmp_dir)
config_dir = tmp_dir / "odbcconfig"
config_dir.mkdir(exist_ok=True)
config_file = config_dir / "odbcinst.ini"
with open(config_file, "w") as f:
f.write(config)
yield config_file
@contextmanager
def odbcconfig(settings):
with temporary_odbc_config(
ODBCINST_INI_TEMPLATE.format(
driver=settings["driver"],
trace="yes" if settings["log"] is not None else "no",
trace_file=settings["log"],
)
) as cfg:
env_vars = {"ODBCSYSINI": f"{cfg.parent.resolve()}"}
with environment(env_vars) as env:
yield cfg, env
@contextmanager
def odbc_connection(settings):
with odbcconfig(settings):
cfg = {
"driver": "EXAODBC",
f"server": f"{settings['db-address']}:{settings['db-port']}",
"user": "sys",
"password": "exasol",
}
connection = connect(
"".join(
[
"DRIVER={driver};",
"EXAHOST={server};",
"UID={user};",
"PWD={password};",
"EXALOGFILE=exa-odbc.trace" if settings['log'] else ""
]
).format(**cfg), autocommit=settings['autocommit']
)
yield connection.cursor()
connection.close()
def insert_scenario(settings):
with odbc_connection(settings) as cursor:
setup_table(cursor)
cursor.execute("INSERT INTO TEST.manual_pk VALUES (1, 'd1');")
cursor.execute("INSERT INTO TEST.manual_pk VALUES (1, 'd1');")
def prepared_insert_scenario(settings):
with odbc_connection(settings) as cursor:
setup_table(cursor)
cursor.execute("INSERT INTO TEST.manual_pk VALUES (?, ?);", (1, "foo"))
cursor.execute("INSERT INTO TEST.manual_pk VALUES (?, ?);", (1, "foo"))
def setup_table(cursor):
cursor.execute("DROP TABLE IF EXISTS TEST.manual_pk")
cursor.execute(
dedent(
"""
CREATE TABLE TEST.manual_pk (
id INTEGER NOT NULL,
"data" VARCHAR(50),
PRIMARY KEY (id)
);
"""
)
)
def system_info():
print("System Information")
print("-" * 50)
print("PYTHON VERSION")
run(["python", "--version"])
print("-" * 50)
print("PYTHON ODBC VERSION")
run(["python", "-m", "pip", "show", "pyodbc"])
print("PLATFORM")
print(platform())
print("EXASOL ODBC DRIVER")
print("libexasolodbc driver to 7.0.11")
def create_parser():
parser = argparse.ArgumentParser()
parser.add_argument(
"scenario",
choices=["insert", "prepared-insert"],
help="Test scenario to execute",
)
parser.add_argument(
"driver",
type=Path,
help="Path to the exasol odbc driver which shall be used.",
)
parser.add_argument(
"--system-info",
action="store_true",
default=False,
help="Print system information.",
)
parser.add_argument(
"--db-address",
default="localhost",
help="DNS name or address of the database server to connect to.",
)
parser.add_argument(
"--db-port", type=int, default=8888, help="Port of the database to connect to."
)
parser.add_argument(
"--odbc-log",
action="store_true",
default=False,
help="Whether or not to store the odbc trace",
)
parser.add_argument(
"--autocommit",
action="store_true",
default=False,
help="Whether or not to store the odbc trace",
)
return parser
def main(argv=None):
parser = create_parser()
args = parser.parse_args(argv)
if args.system_info:
system_info()
settings = {
"db-address": args.db_address,
"db-port": args.db_port,
"driver": args.driver,
"autocommit": args.autocommit,
"log": Path(".").joinpath("odbc.trace") if args.odbc_log else None,
}
scenario = {
"insert": insert_scenario,
"prepared-insert": prepared_insert_scenario,
}[args.scenario]
scenario(settings)
sys.exit(0)
if __name__ == "__main__":
main() |
Discussion ResultsDiscussion and analysis with the Exasol interface team showed that the observed behavior is the expected one. The script in the comment above was updated so this can be validated by running the following command:
Follow upDiscuss and consider how to address this in Potential Courses of Action
|
Update On Current AnalysisA more thorough analysis has shown, that the disabled unit test uncovered a couple of similar, but different ScenariosThe following scenarios will trigger (uncover) the different error scenarios found with the sqlalchemy-exasol plugin, SummaryTry to insert exactly the same row twice, including the same PK using the sqlalchemy class abstractions. Variations/SettingsDialect:
Auto commit:
Dialect:
|
Follow Up
|
This issue will be closed and the sub issues which have been found will be used to track and investigate and fix the individual
|
The test case ExceptionTest_exasol_pyodbc::()::test_integrity_error (added with SQLA 1.0.5 fails). The test expects an exception upon insert with a duplicate key. However, the exception is not raised.
link to test case:
https://github.com/zzzeek/sqlalchemy/blob/0766c80b9c02fdbad3203835ab850ad690f4c03b/lib/sqlalchemy/testing/suite/test_dialect.py#L28
The text was updated successfully, but these errors were encountered: