Skip to content

Commit ae3010f

Browse files
author
Eugene Shershen
committed
implement UUID parameter binding
1 parent 99ef46d commit ae3010f

4 files changed

Lines changed: 28 additions & 17 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,4 @@ clean: ## Clean up Docker containers and volumes
8080
dev-setup: install docker-up ## Complete development setup
8181
@echo "Development environment is ready!"
8282
@echo "Run 'make test' to run tests with PostgreSQL"
83-
@echo "Run 'make docker-down' to stop PostgreSQL when done"
83+
@echo "Run 'make docker-down' to stop PostgreSQL when done"

psqlpy_sqlalchemy/connection.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,26 @@ async def _prepare_execute(
6868
querystring, processed_parameters
6969
)
7070
)
71-
71+
7272
# Handle mixed parameter styles specifically for explicit PostgreSQL casting
7373
# Only trigger this for queries with explicit casting syntax like :param::TYPE
74-
if (converted_params is not None and
75-
not isinstance(converted_params, dict) and
76-
converted_query == querystring): # Query unchanged means mixed parameters detected
77-
74+
if (
75+
converted_params is not None
76+
and not isinstance(converted_params, dict)
77+
and converted_query == querystring
78+
): # Query unchanged means mixed parameters detected
7879
import re
80+
7981
# Look specifically for PostgreSQL casting syntax :param::TYPE
8082
casting_pattern = r":([a-zA-Z_][a-zA-Z0-9_]*)::"
8183
casting_matches = re.findall(casting_pattern, converted_query)
82-
84+
8385
if casting_matches:
8486
# This is a known limitation: SQLAlchemy can't handle named parameters with explicit PostgreSQL casting
8587
import logging
86-
logger = logging.getLogger(__name__)
87-
88+
89+
logging.getLogger(__name__)
90+
8891
raise RuntimeError(
8992
f"Named parameters with explicit PostgreSQL casting are not supported. "
9093
f"Found casting parameters: {casting_matches} in query: {converted_query[:100]}... "
@@ -200,7 +203,7 @@ def _convert_named_params_with_casting(
200203
import logging
201204

202205
logger = logging.getLogger(__name__)
203-
206+
204207
logger.debug(
205208
f"Parameter conversion called - Query: {querystring!r}, "
206209
f"Parameters: {parameters!r}, Parameters type: {type(parameters)}"

tests/test_poolclass_compatibility.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@ def tearDown(self):
4242
except RuntimeError:
4343
loop = asyncio.new_event_loop()
4444
asyncio.set_event_loop(loop)
45-
45+
4646
# Run the disposal in the event loop
4747
if not loop.is_running():
4848
loop.run_until_complete(self.async_engine.dispose())
4949
else:
5050
# If loop is already running, create a task
5151
import concurrent.futures
52+
5253
with concurrent.futures.ThreadPoolExecutor() as executor:
5354
future = executor.submit(
5455
lambda: asyncio.run(self.async_engine.dispose())

tests/test_uuid_support.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,27 @@ def _is_docker_postgres_available():
3434
try:
3535
import socket
3636
import subprocess
37-
37+
3838
# Check if Docker is installed and running
3939
try:
4040
result = subprocess.run(
41-
["docker", "ps", "--filter", "name=psqlpy-postgres", "--format", "{{.Names}}"],
41+
[
42+
"docker",
43+
"ps",
44+
"--filter",
45+
"name=psqlpy-postgres",
46+
"--format",
47+
"{{.Names}}",
48+
],
4249
capture_output=True,
4350
text=True,
44-
timeout=5
51+
timeout=5,
4552
)
4653
if "psqlpy-postgres" in result.stdout:
4754
# Container is running, check if PostgreSQL is accessible
4855
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
4956
sock.settimeout(2)
50-
result = sock.connect_ex(('localhost', 5432))
57+
result = sock.connect_ex(("localhost", 5432))
5158
sock.close()
5259
return result == 0
5360
except (subprocess.TimeoutExpired, FileNotFoundError):
@@ -156,7 +163,7 @@ async def test_uuid_string_parameter(self, engine):
156163

157164
async def test_uuid_with_explicit_cast(self, engine):
158165
"""Test UUID parameter handling without problematic explicit casting syntax.
159-
166+
160167
This test demonstrates the correct way to handle UUID parameters:
161168
- Use named parameters without explicit casting (SQLAlchemy handles type conversion)
162169
- Avoid the combination of named parameters with explicit PostgreSQL casting syntax
@@ -184,7 +191,7 @@ async def test_uuid_with_explicit_cast(self, engine):
184191
rows = result.fetchall()
185192
assert len(rows) == 1
186193
assert rows[0].name == "test_cast"
187-
194+
188195
# Also test with UUID object (not just string)
189196
result2 = await conn.execute(
190197
text(

0 commit comments

Comments
 (0)