Skip to content

Commit 7adae7b

Browse files
authored
Refactoring/610 use text construct for strings passed to execute (#611)
* Set SQLALCHEMY_WARN_20 in environment to output deprecation warnings in tests * Set the deprecation we want to fix as an error to explicitly ensure we resolve * Rename so clearer that control connection is from pyexasol and not sqlalchemy-exasol * Resolve string to execute for test:regression * Resolve string to execute for test:exasol * Resolve string to execute for test:sqla * Run project:fix on files * Update pre-commit-config
1 parent fc094ba commit 7adae7b

21 files changed

+241
-168
lines changed

.github/workflows/checks.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ jobs:
180180
python-version: ${{ matrix.python-version }}
181181

182182
- name: Run Tests and Collect Coverage
183-
run: poetry run -- nox -s test:unit -- --coverage
183+
run: |
184+
export SQLALCHEMY_WARN_20=1
185+
poetry run -- nox -s test:unit -- --coverage
184186
185187
- name: Upload Artifacts
186188
uses: actions/[email protected]

.github/workflows/slow-checks.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ jobs:
3535
run: sudo apt-get install unixodbc unixodbc-dev libboost-date-time-dev libboost-locale-dev libboost-system-dev
3636

3737
- name: Run Tests and Collect Coverage
38-
run: poetry run -- nox -s test:integration -- --coverage --db-version ${{ matrix.exasol-version }}
38+
run: |
39+
export SQLALCHEMY_WARN_20=1
40+
poetry run -- nox -s test:integration -- --coverage --db-version ${{ matrix.exasol-version }}
3941
4042
- name: Upload Artifacts
4143
uses: actions/[email protected]

.pre-commit-config.yaml

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,42 @@
1-
default_stages: [commit]
1+
default_stages: [ pre-commit, pre-push ]
22
repos:
3-
- repo: local
3+
4+
- repo: local
5+
hooks:
6+
- id: code-format
7+
name: code-format
8+
types: [ python ]
9+
pass_filenames: false
10+
language: system
11+
entry: poetry run -- nox -s project:fix
12+
stages: [ pre-commit ]
13+
14+
- repo: local
415
hooks:
5-
- id: code-format
6-
name: code-format
7-
types: [python]
8-
pass_filenames: false
9-
language: system
10-
entry: poetry run -- python -m nox -s project:fix
16+
- id: type-check
17+
name: type-check
18+
types: [ python ]
19+
pass_filenames: false
20+
language: system
21+
entry: poetry run -- nox -s lint:typing
22+
stages: [ pre-push ]
1123

12-
- repo: local
24+
- repo: local
1325
hooks:
14-
- id: type-check
15-
name: type-check
16-
types: [python]
17-
pass_filenames: false
18-
language: system
19-
entry: poetry run -- python -m nox -s lint:typing
26+
- id: lint
27+
name: lint
28+
types: [ python ]
29+
pass_filenames: false
30+
language: system
31+
entry: poetry run -- nox -s lint:code
32+
stages: [ pre-push ]
2033

21-
- repo: local
34+
- repo: https://github.com/pre-commit/pre-commit-hooks
35+
rev: v5.0.0
2236
hooks:
23-
- id: lint
24-
name: lint
25-
types: [python]
26-
pass_filenames: false
27-
language: system
28-
entry: poetry run -- python -m nox -s lint:code
37+
- id: check-yaml
38+
stages: [ pre-commit ]
39+
- id: end-of-file-fixer
40+
stages: [ pre-commit ]
41+
- id: trailing-whitespace
42+
stages: [ pre-commit ]

README.rst

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,10 @@ Using SQLAlchemy with EXASOL DB
9797
9898
from sqlalchemy import create_engine
9999
url = "exa+websocket://A_USER:[email protected]:1234/my_schema?CONNECTIONLCALL=en_US.UTF-8"
100-
e = create_engine(url)
101-
r = e.execute("select 42 from dual").fetchall()
100+
e = create_engine(url)
101+
query = "select 42 from dual"
102+
with engine.connect() as con:
103+
result = con.execute(sql.text(query)).fetchall()
102104
103105
Examples:
104106

@@ -132,17 +134,21 @@ Examples:
132134
133135
from sqlalchemy import create_engine
134136
url = "exa+pyodbc://A_USER:[email protected]:1234/my_schema?CONNECTIONLCALL=en_US.UTF-8&driver=EXAODBC"
135-
e = create_engine(url)
136-
r = e.execute("select 42 from dual").fetchall()
137+
e = create_engine(url)
138+
query = "select 42 from dual"
139+
with engine.connect() as con:
140+
result = con.execute(sql.text(query)).fetchall()
137141
138142
**Turbodbc (ODBC based Dialect):**
139143

140144
.. code-block:: python
141145
142146
from sqlalchemy import create_engine
143147
url = "exa+turbodbc://A_USER:[email protected]:1234/my_schema?CONNECTIONLCALL=en_US.UTF-8&driver=EXAODBC"
144-
e = create_engine(url)
145-
r = e.execute("select 42 from dual").fetchall()
148+
e = create_engine(url)
149+
query = "select 42 from dual"
150+
with engine.connect() as con:
151+
result = con.execute(sql.text(query)).fetchall()
146152
147153
148154
Features

doc/changes/unreleased.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ This allows us to use the latest dependencies, which do not have open vulnerabil
77

88
- #612: Updated CI tests to run against Exasol DB versions 7.1.30, 8.34.0, and 2025.1.0. Dropped support for Python 3.9.
99

10-
## 🧰 Internal
10+
## Refactoring
1111

12-
- #558 Updated to poetry 2.1.2 & relocked dependencies to resolve CVE-2025-27516
12+
- #610: Altered string input into `Connection.execute()` to be handled properly
13+
14+
## Internal
15+
16+
- #558: Updated to poetry 2.1.2 & relocked dependencies to resolve CVE-2025-27516
1317
- #548: Replaced pytest-exasol-itde with pytest-backend
14-
- - Relocked dependencies to resolve CVE-2025-43859
18+
- Relocked dependencies to resolve CVE-2025-43859
1519
- #564: Replaced nox test:unit with that from exasol-toolbox
1620
- Reformatted files to meet project specifications
1721
- #588: Updated to exasol-toolbox 1.6.0 and relocked dependencies to resolve CVE-2025-50182, CVE-2025-50181, & CVE-2024-47081
18-
- #605: Removed non-ASCII unicode from templates & relocked dependencies to resolve CVE-2025-8869 (pip -> transitive dependency)
22+
- #605: Removed non-ASCII unicode from templates & relocked dependencies to resolve CVE-2025-8869 (pip -> transitive dependency)

doc/user_guide.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ Getting Started
2222

2323
.. code-block:: python
2424
25-
from sqlalchemy import create_engine
25+
from sqlalchemy import create_engine, sql
2626
url = "exa+pyodbc://A_USER:[email protected]:1234/my_schema?CONNECTIONLCALL=en_US.UTF-8&driver=EXAODBC"
2727
e = create_engine(url)
28-
r = e.execute("select 42 from dual").fetchall()
28+
query = "select 42 from dual"
29+
with engine.connect() as con:
30+
result = con.execute(sql.text(query)).fetchall()
2931
3032
31-
For more details on SQLAlchemy consult it's `documenation <https://docs.sqlalchemy.org/en/13/>`_.
33+
For more details on SQLAlchemy consult it's `documentation <https://docs.sqlalchemy.org/en/13/>`_.
3234

3335
Readme
3436
~~~~~~

noxfile.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ def parser() -> ArgumentParser:
6161
"--db-version",
6262
choices=PROJECT_CONFIG.exasol_versions,
6363
default=PROJECT_CONFIG.exasol_versions[0],
64-
help="which will be used",
6564
)
6665
return p
6766

@@ -125,7 +124,6 @@ def parser() -> ArgumentParser:
125124
"--connector",
126125
choices=PROJECT_CONFIG.connectors,
127126
default=PROJECT_CONFIG.connectors[0],
128-
help="which will be used",
129127
)
130128
return p
131129

@@ -157,7 +155,6 @@ def parser() -> ArgumentParser:
157155
"--connector",
158156
choices=PROJECT_CONFIG.connectors,
159157
default=PROJECT_CONFIG.connectors[0],
160-
help="which will be used",
161158
)
162159
return p
163160

@@ -199,13 +196,11 @@ def parser() -> ArgumentParser:
199196
"--connector",
200197
choices=PROJECT_CONFIG.connectors,
201198
default=PROJECT_CONFIG.connectors[0],
202-
help="which will be used",
203199
)
204200
p.add_argument(
205201
"--db-version",
206202
choices=PROJECT_CONFIG.exasol_versions,
207203
default=PROJECT_CONFIG.exasol_versions[0],
208-
help="which will be used",
209204
)
210205
p.add_argument(
211206
"--coverage",
@@ -223,15 +218,15 @@ def parser() -> ArgumentParser:
223218
posargs=["--db-version", f"{args.db_version}"],
224219
)
225220
session.notify(
226-
find_session_runner(session, f"test:sqla"),
221+
find_session_runner(session, "test:sqla"),
227222
posargs=["--connector", f"{args.connector}"],
228223
)
229224
session.notify(
230-
find_session_runner(session, f"test:exasol"),
225+
find_session_runner(session, "test:exasol"),
231226
posargs=["--connector", f"{args.connector}"],
232227
)
233228
session.notify(
234-
find_session_runner(session, f"test:regression"),
229+
find_session_runner(session, "test:regression"),
235230
)
236231
session.notify(find_session_runner(session, "db:stop"))
237232

@@ -271,14 +266,14 @@ def report_skipped(session: Session) -> None:
271266

272267

273268
def _connector_matrix(config: Config):
274-
CONNECTORS = ["websocket"]
269+
connectors_list = ["websocket"]
275270
attr = "connectors"
276-
connectors = getattr(config, attr, CONNECTORS)
271+
connectors = getattr(config, attr, connectors_list)
277272
if not hasattr(config, attr):
278273
_log.warning(
279274
"Config does not contain '%s' setting. Using default: %s",
280275
attr,
281-
CONNECTORS,
276+
connectors_list,
282277
)
283278
return {"connector": connectors}
284279

pyproject.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,12 @@ exasol-toolbox = "^1.9.0"
9292
[tool.pytest.ini_options]
9393
addopts = "--tb native -v -r fxX"
9494
filterwarnings = [
95-
"error::DeprecationWarning",
96-
"ignore::DeprecationWarning:sqlalchemy.testing.plugin.*",
97-
"ignore::DeprecationWarning:sqlalchemy_exasol.*",
95+
# before end of #413, switch this from a text specific issue to a general error on a warning to ensure known deprecation issues have been resolved
96+
"error:.*Passing a string.*",
97+
# this is used for turbodbc and pyodbc as historically we'd like to remove them.
98+
# thus far, it seems like this is not a strict requirement for the migration,
99+
# so we will ignore them.
100+
"ignore::sqlalchemy_exasol.warnings.SqlaExasolDeprecationWarning"
98101
]
99102

100103
[tool.black]
@@ -128,4 +131,4 @@ follow_untyped_imports = true
128131
[tool.sonar]
129132
projectKey = "com.exasol:sqlalchemy-exasol"
130133
hostUrl = "https://sonarcloud.io"
131-
organization = "exasol"
134+
organization = "exasol"

sqlalchemy_exasol/base.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
from sqlalchemy import (
5454
event,
5555
schema,
56+
select,
5657
sql,
5758
)
5859
from sqlalchemy import types as sqltypes
@@ -800,7 +801,7 @@ def _get_server_version_info(self, connection):
800801
"select PARAM_VALUE from SYS.EXA_METADATA"
801802
" where PARAM_NAME = 'databaseProductVersion'"
802803
)
803-
result = connection.execute(query).fetchone()[0].split(".")
804+
result = connection.execute(sql.text(query)).fetchone()[0].split(".")
804805
major, minor, patch = 0, 0, 0
805806
major = int(result[0])
806807
minor = int(result[1])
@@ -894,7 +895,7 @@ def _get_schema_for_input(self, connection, schema):
894895
@staticmethod
895896
def _get_current_schema(connection):
896897
sql_statement = "SELECT CURRENT_SCHEMA"
897-
current_schema = connection.execute(sql_statement).fetchone()[0]
898+
current_schema = connection.execute(sql.text(sql_statement)).fetchone()[0]
898899
return current_schema
899900

900901
@reflection.cache
@@ -905,7 +906,7 @@ def get_table_names(self, connection, schema, **kw):
905906
)
906907
if schema is None:
907908
sql_statement += "CURRENT_SCHEMA ORDER BY table_name"
908-
result = connection.execute(sql_statement)
909+
result = connection.execute(sql.text(sql_statement))
909910
else:
910911
sql_statement += ":schema ORDER BY table_name"
911912
result = connection.execute(

sqlalchemy_exasol/pyodbc.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def _get_columns(self, connection, table_name, schema=None, **kw):
250250
sql_statement = sql_statement.format(
251251
schema=quoted_schema_string, table=quoted_table_string
252252
)
253-
response = connection.execute(sql_statement)
253+
response = connection.execute(sql.text(sql_statement))
254254

255255
return list(response)
256256

@@ -295,7 +295,7 @@ def _get_foreign_keys(self, connection, table_name, schema=None, **kw):
295295
quoted_schema_string, quoted_table_string, "FOREIGN KEY"
296296
)
297297
)
298-
response = connection.execute(sql_statement)
298+
response = connection.execute(sql.text(sql_statement))
299299

300300
return list(response)
301301

0 commit comments

Comments
 (0)