velocity-python 0.0.137__py3-none-any.whl → 0.0.138__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of velocity-python might be problematic. Click here for more details.
- velocity/__init__.py +1 -1
- velocity/db/core/engine.py +23 -1
- velocity/db/servers/postgres/sql.py +41 -13
- {velocity_python-0.0.137.dist-info → velocity_python-0.0.138.dist-info}/METADATA +1 -1
- {velocity_python-0.0.137.dist-info → velocity_python-0.0.138.dist-info}/RECORD +8 -8
- {velocity_python-0.0.137.dist-info → velocity_python-0.0.138.dist-info}/WHEEL +0 -0
- {velocity_python-0.0.137.dist-info → velocity_python-0.0.138.dist-info}/licenses/LICENSE +0 -0
- {velocity_python-0.0.137.dist-info → velocity_python-0.0.138.dist-info}/top_level.txt +0 -0
velocity/__init__.py
CHANGED
velocity/db/core/engine.py
CHANGED
|
@@ -367,12 +367,34 @@ class Engine:
|
|
|
367
367
|
|
|
368
368
|
msg = str(exception).strip().lower()
|
|
369
369
|
|
|
370
|
-
# Create enhanced error message with SQL query
|
|
370
|
+
# Create enhanced error message with SQL query and context
|
|
371
371
|
enhanced_message = str(exception)
|
|
372
|
+
|
|
373
|
+
# Add specific guidance for common WHERE clause errors
|
|
374
|
+
exception_str_lower = str(exception).lower()
|
|
375
|
+
if "argument of where must be type boolean" in exception_str_lower:
|
|
376
|
+
enhanced_message += (
|
|
377
|
+
"\n\n*** WHERE CLAUSE ERROR ***\n"
|
|
378
|
+
"This error typically occurs when a WHERE clause contains a bare value "
|
|
379
|
+
"instead of a proper boolean expression.\n"
|
|
380
|
+
"Common fixes:\n"
|
|
381
|
+
" - Change WHERE 1001 to WHERE sys_id = 1001\n"
|
|
382
|
+
" - Change WHERE {'column': value} format in dictionaries\n"
|
|
383
|
+
" - Ensure string WHERE clauses are complete SQL expressions"
|
|
384
|
+
)
|
|
385
|
+
|
|
372
386
|
if sql:
|
|
373
387
|
enhanced_message += (
|
|
374
388
|
f"\n\nSQL Query:\n{self._format_sql_with_params(sql, parameters)}"
|
|
375
389
|
)
|
|
390
|
+
|
|
391
|
+
# Add call stack context for better debugging
|
|
392
|
+
import traceback
|
|
393
|
+
stack_trace = traceback.format_stack()
|
|
394
|
+
# Get the last few frames that aren't in the error handling itself
|
|
395
|
+
relevant_frames = [frame for frame in stack_trace if 'process_error' not in frame and 'logging' not in frame][-3:]
|
|
396
|
+
if relevant_frames:
|
|
397
|
+
enhanced_message += "\n\nCall Context:\n" + "".join(relevant_frames)
|
|
376
398
|
|
|
377
399
|
# Format SQL for logging
|
|
378
400
|
formatted_sql_info = ""
|
|
@@ -69,7 +69,7 @@ class SQL(BaseSQLDialect):
|
|
|
69
69
|
|
|
70
70
|
default_schema = "public"
|
|
71
71
|
|
|
72
|
-
ApplicationErrorCodes = ["22P02", "42883", "42501", "42601", "25P01", "25P02"]
|
|
72
|
+
ApplicationErrorCodes = ["22P02", "42883", "42501", "42601", "25P01", "25P02", "42804"] # Added 42804 for datatype mismatch
|
|
73
73
|
|
|
74
74
|
DatabaseMissingErrorCodes = ["3D000"]
|
|
75
75
|
TableMissingErrorCodes = ["42P01"]
|
|
@@ -296,23 +296,37 @@ class SQL(BaseSQLDialect):
|
|
|
296
296
|
else:
|
|
297
297
|
sql_parts["FROM"].append(TableHelper.quote(table))
|
|
298
298
|
|
|
299
|
-
# WHERE
|
|
299
|
+
# WHERE - Enhanced validation to prevent malformed SQL
|
|
300
300
|
if where:
|
|
301
301
|
if isinstance(where, str):
|
|
302
302
|
# Validate string WHERE clauses to prevent malformed SQL
|
|
303
|
-
|
|
303
|
+
where_stripped = where.strip()
|
|
304
|
+
if not where_stripped:
|
|
305
|
+
raise ValueError("WHERE clause cannot be empty string.")
|
|
306
|
+
# Check for boolean literals first (includes '1' and '0')
|
|
307
|
+
if where_stripped in ('True', 'False', '1', '0'):
|
|
304
308
|
raise ValueError(
|
|
305
309
|
f"Invalid WHERE clause: '{where}'. "
|
|
306
|
-
"
|
|
307
|
-
"
|
|
310
|
+
"Boolean literals alone are not valid WHERE clauses. "
|
|
311
|
+
"Use complete SQL expressions like 'sys_active = true' instead."
|
|
312
|
+
)
|
|
313
|
+
# Then check for other numeric values (excluding '1' and '0' already handled above)
|
|
314
|
+
elif where_stripped.isdigit():
|
|
315
|
+
raise ValueError(
|
|
316
|
+
f"Invalid WHERE clause: '{where}'. "
|
|
317
|
+
"Bare integers are not valid WHERE clauses. "
|
|
318
|
+
"Use a dictionary like {{'sys_id': {where_stripped}}} or "
|
|
319
|
+
f"a complete SQL expression like 'sys_id = {where_stripped}' instead."
|
|
308
320
|
)
|
|
309
321
|
sql_parts["WHERE"].append(where)
|
|
310
322
|
elif isinstance(where, (int, float, bool)):
|
|
311
323
|
# Handle primitive types that should be converted to proper WHERE clauses
|
|
324
|
+
suggested_fix = "{'sys_id': " + str(where) + "}" if isinstance(where, int) else "complete SQL expression"
|
|
312
325
|
raise ValueError(
|
|
313
326
|
f"Invalid WHERE clause: {where} (type: {type(where).__name__}). "
|
|
314
|
-
"
|
|
315
|
-
"
|
|
327
|
+
f"Primitive values cannot be WHERE clauses directly. "
|
|
328
|
+
f"Use a dictionary like {suggested_fix} or a complete SQL string instead. "
|
|
329
|
+
f"This error prevents PostgreSQL 'argument of WHERE must be type boolean' errors."
|
|
316
330
|
)
|
|
317
331
|
elif isinstance(where, Mapping):
|
|
318
332
|
# Convert dictionary to predicate list
|
|
@@ -473,20 +487,34 @@ class SQL(BaseSQLDialect):
|
|
|
473
487
|
new_where.append(th.make_predicate(key, val))
|
|
474
488
|
where = new_where
|
|
475
489
|
elif isinstance(where, str):
|
|
476
|
-
#
|
|
477
|
-
|
|
490
|
+
# Enhanced validation for string WHERE clauses
|
|
491
|
+
where_stripped = where.strip()
|
|
492
|
+
if not where_stripped:
|
|
493
|
+
raise ValueError("WHERE clause cannot be empty string.")
|
|
494
|
+
# Check for boolean literals first (includes '1' and '0')
|
|
495
|
+
if where_stripped in ('True', 'False', '1', '0'):
|
|
496
|
+
raise ValueError(
|
|
497
|
+
f"Invalid WHERE clause: '{where}'. "
|
|
498
|
+
"Boolean literals alone are not valid WHERE clauses. "
|
|
499
|
+
"Use complete SQL expressions like 'sys_active = true' instead."
|
|
500
|
+
)
|
|
501
|
+
# Then check for other numeric values (excluding '1' and '0' already handled above)
|
|
502
|
+
elif where_stripped.isdigit():
|
|
478
503
|
raise ValueError(
|
|
479
504
|
f"Invalid WHERE clause: '{where}'. "
|
|
480
|
-
"
|
|
481
|
-
"
|
|
505
|
+
"Bare integers are not valid WHERE clauses. "
|
|
506
|
+
f"Use a dictionary like {{'sys_id': {where_stripped}}} or "
|
|
507
|
+
f"a complete SQL expression like 'sys_id = {where_stripped}' instead."
|
|
482
508
|
)
|
|
483
509
|
where_clauses.append(where)
|
|
484
510
|
elif isinstance(where, (int, float, bool)):
|
|
485
511
|
# Handle primitive types that should be converted to proper WHERE clauses
|
|
512
|
+
suggested_fix = "{'sys_id': " + str(where) + "}" if isinstance(where, int) else "complete SQL expression"
|
|
486
513
|
raise ValueError(
|
|
487
514
|
f"Invalid WHERE clause: {where} (type: {type(where).__name__}). "
|
|
488
|
-
"
|
|
489
|
-
"
|
|
515
|
+
f"Primitive values cannot be WHERE clauses directly. "
|
|
516
|
+
f"Use a dictionary like {suggested_fix} or a complete SQL string instead. "
|
|
517
|
+
f"This error prevents PostgreSQL 'argument of WHERE must be type boolean' errors."
|
|
490
518
|
)
|
|
491
519
|
|
|
492
520
|
# Process the where clause if it's a list of tuples
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
velocity/__init__.py,sha256=
|
|
1
|
+
velocity/__init__.py,sha256=4cK9msUzcPYo3tFiZ2-Ww6__hxYNmQ_B876ClZvAKwY,147
|
|
2
2
|
velocity/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
velocity/app/invoices.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
velocity/app/orders.py,sha256=fr1oTBjSFfyeMBUXRG06LV4jgwrlwYNL5mbEBleFwf0,6328
|
|
@@ -32,7 +32,7 @@ velocity/db/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
|
|
|
32
32
|
velocity/db/core/column.py,sha256=tAr8tL3a2nyaYpNHhGl508FrY_pGZTzyYgjAV5CEBv4,4092
|
|
33
33
|
velocity/db/core/database.py,sha256=3zNGItklu9tZCKsbx2T2vCcU1so8AL9PPL0DLjvaz6s,3554
|
|
34
34
|
velocity/db/core/decorators.py,sha256=quhjMoEmK_l2jF7jXyL5Fgv8uisIpBz34Au5d3U6UHs,5276
|
|
35
|
-
velocity/db/core/engine.py,sha256=
|
|
35
|
+
velocity/db/core/engine.py,sha256=mNlaFPruHO935phKPVrsxZprGYUvxW-zp2sBcBZ-KCg,20666
|
|
36
36
|
velocity/db/core/result.py,sha256=b0ie3yZAOj9S57x32uFFGKZ95zhImmZ0iXl0X1qYszc,12813
|
|
37
37
|
velocity/db/core/row.py,sha256=yqxm03uEDy3oSbnkCtKyiqFdSqG3zXTq2HIHYKOvPY4,7291
|
|
38
38
|
velocity/db/core/sequence.py,sha256=VMBc0ZjGnOaWTwKW6xMNTdP8rZ2umQ8ml4fHTTwuGq4,3904
|
|
@@ -53,7 +53,7 @@ velocity/db/servers/mysql/types.py,sha256=BMQf4TpsRo1JN-yOl1nSItTO-Juu2piSTNy5o_
|
|
|
53
53
|
velocity/db/servers/postgres/__init__.py,sha256=6YcTLXposmsrEaJgdUAM_QgD1TZDSILQrGcwWZ-dibk,2457
|
|
54
54
|
velocity/db/servers/postgres/operators.py,sha256=y9k6enReeR5hJxU_lYYR2epoaw4qCxEqmYJJ5jjaVWA,1166
|
|
55
55
|
velocity/db/servers/postgres/reserved.py,sha256=5tKLaqFV-HrWRj-nsrxl5KGbmeM3ukn_bPZK36XEu8M,3648
|
|
56
|
-
velocity/db/servers/postgres/sql.py,sha256=
|
|
56
|
+
velocity/db/servers/postgres/sql.py,sha256=tC-_kl2gYRZKvW5zxOxvdMv0ZXJrO4zpnjcXVuro9q0,47246
|
|
57
57
|
velocity/db/servers/postgres/types.py,sha256=W71x8iRx-IIJkQSjb29k-KGkqp-QS6SxB0BHYXd4k8w,6955
|
|
58
58
|
velocity/db/servers/sqlite/__init__.py,sha256=EIx09YN1-Vm-4CXVcEf9DBgvd8FhIN9rEqIaSRrEcIk,2293
|
|
59
59
|
velocity/db/servers/sqlite/operators.py,sha256=VzZgph8RrnHkIVqqWGqnJwcafgBzc_8ZQp-M8tMl-mw,1221
|
|
@@ -121,8 +121,8 @@ velocity/misc/tests/test_merge.py,sha256=Vm5_jY5cVczw0hZF-3TYzmxFw81heJOJB-dvhCg
|
|
|
121
121
|
velocity/misc/tests/test_oconv.py,sha256=fy4DwWGn_v486r2d_3ACpuBD-K1oOngNq1HJCGH7X-M,4694
|
|
122
122
|
velocity/misc/tests/test_original_error.py,sha256=iWSd18tckOA54LoPQOGV5j9LAz2W-3_ZOwmyZ8-4YQc,1742
|
|
123
123
|
velocity/misc/tests/test_timer.py,sha256=l9nrF84kHaFofvQYKInJmfoqC01wBhsUB18lVBgXCoo,2758
|
|
124
|
-
velocity_python-0.0.
|
|
125
|
-
velocity_python-0.0.
|
|
126
|
-
velocity_python-0.0.
|
|
127
|
-
velocity_python-0.0.
|
|
128
|
-
velocity_python-0.0.
|
|
124
|
+
velocity_python-0.0.138.dist-info/licenses/LICENSE,sha256=aoN245GG8s9oRUU89KNiGTU4_4OtnNmVi4hQeChg6rM,1076
|
|
125
|
+
velocity_python-0.0.138.dist-info/METADATA,sha256=Rt_XjAFeisvsIMrNAx1j4whaIjqHk8aHcFKg7IOGIxk,34262
|
|
126
|
+
velocity_python-0.0.138.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
127
|
+
velocity_python-0.0.138.dist-info/top_level.txt,sha256=JW2vJPmodgdgSz7H6yoZvnxF8S3fTMIv-YJWCT1sNW0,9
|
|
128
|
+
velocity_python-0.0.138.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|