t-sql 4.9.3__tar.gz → 4.10.0__tar.gz
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.
- {t_sql-4.9.3 → t_sql-4.10.0}/PKG-INFO +1 -1
- {t_sql-4.9.3 → t_sql-4.10.0}/pyproject.toml +1 -1
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_query_builder.py +42 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tsql/query_builder.py +12 -3
- {t_sql-4.9.3 → t_sql-4.10.0}/.dockerignore +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/.github/workflows/publish.yml +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/.github/workflows/test.yml +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/.gitignore +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/Dockerfile +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/LICENSE +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/README.md +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/compose.yaml +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/context7.json +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/pytest.ini +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_alembic_integration.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_asyncpg_integration.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_deep_nesting.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_different_object_types.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_error_messages.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_escaped.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_escaped_binary_hex.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_helper_functions.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_injection_edge_cases.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_injection_protection_validation.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_injections_for_escaped.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_like_patterns.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_mysql_integration.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_parameter_names.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_sqlalchemy_integration.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_sqlite_integration.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_string_based_builders.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_styles.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_template_in_builders.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_tsql.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tests/test_type_processor.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tsql/__init__.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tsql/row.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tsql/styles.py +0 -0
- {t_sql-4.9.3 → t_sql-4.10.0}/tsql/type_processor.py +0 -0
|
@@ -1545,3 +1545,45 @@ def test_multiple_recursive_ctes():
|
|
|
1545
1545
|
assert sql.startswith("WITH RECURSIVE")
|
|
1546
1546
|
assert "normal AS" in sql
|
|
1547
1547
|
assert "tree AS" in sql
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
def test_where_with_bare_boolean_column():
|
|
1551
|
+
"""Test WHERE with bare boolean column (truthy check)"""
|
|
1552
|
+
class Contacts(Table):
|
|
1553
|
+
id: Column
|
|
1554
|
+
is_primary: Column
|
|
1555
|
+
|
|
1556
|
+
query = Contacts.select().where(Contacts.is_primary)
|
|
1557
|
+
sql, params = query.render()
|
|
1558
|
+
|
|
1559
|
+
assert 'WHERE contacts.is_primary' in sql
|
|
1560
|
+
assert params == []
|
|
1561
|
+
|
|
1562
|
+
|
|
1563
|
+
def test_update_where_with_bare_boolean_column():
|
|
1564
|
+
"""Test UPDATE WHERE with bare boolean column"""
|
|
1565
|
+
class Contacts(Table):
|
|
1566
|
+
id: Column
|
|
1567
|
+
is_primary: Column
|
|
1568
|
+
name: Column
|
|
1569
|
+
|
|
1570
|
+
query = Contacts.update(name='updated').where(Contacts.is_primary)
|
|
1571
|
+
sql, params = query.render()
|
|
1572
|
+
|
|
1573
|
+
assert 'UPDATE contacts SET' in sql
|
|
1574
|
+
assert 'WHERE contacts.is_primary' in sql
|
|
1575
|
+
assert params == ['updated']
|
|
1576
|
+
|
|
1577
|
+
|
|
1578
|
+
def test_delete_where_with_bare_boolean_column():
|
|
1579
|
+
"""Test DELETE WHERE with bare boolean column"""
|
|
1580
|
+
class Contacts(Table):
|
|
1581
|
+
id: Column
|
|
1582
|
+
is_primary: Column
|
|
1583
|
+
|
|
1584
|
+
query = Contacts.delete().where(Contacts.is_primary)
|
|
1585
|
+
sql, params = query.render()
|
|
1586
|
+
|
|
1587
|
+
assert 'DELETE FROM contacts' in sql
|
|
1588
|
+
assert 'WHERE contacts.is_primary' in sql
|
|
1589
|
+
assert params == []
|
|
@@ -932,7 +932,7 @@ class UpdateBuilder(QueryBuilder):
|
|
|
932
932
|
string_table = _StringTable(table_name, schema)
|
|
933
933
|
return cls(string_table, values)
|
|
934
934
|
|
|
935
|
-
def where(self, condition: Union[Condition, Template]) -> 'UpdateBuilder':
|
|
935
|
+
def where(self, condition: Union[Condition, Template, Column]) -> 'UpdateBuilder':
|
|
936
936
|
"""Add a WHERE condition (multiple calls are ANDed together)"""
|
|
937
937
|
self._conditions.append(condition)
|
|
938
938
|
self._requires_where = False
|
|
@@ -994,6 +994,9 @@ class UpdateBuilder(QueryBuilder):
|
|
|
994
994
|
for cond in self._conditions:
|
|
995
995
|
if isinstance(cond, Template):
|
|
996
996
|
where_parts.append(t'({cond})')
|
|
997
|
+
elif isinstance(cond, Column):
|
|
998
|
+
col_str = str(cond)
|
|
999
|
+
where_parts.append(t'{col_str:literal}')
|
|
997
1000
|
else:
|
|
998
1001
|
where_parts.append(cond.to_tsql())
|
|
999
1002
|
combined_where = t_join(t' AND ', where_parts)
|
|
@@ -1057,7 +1060,7 @@ class DeleteBuilder(QueryBuilder):
|
|
|
1057
1060
|
string_table = _StringTable(table_name, schema)
|
|
1058
1061
|
return cls(string_table)
|
|
1059
1062
|
|
|
1060
|
-
def where(self, condition: Union[Condition, Template]) -> 'DeleteBuilder':
|
|
1063
|
+
def where(self, condition: Union[Condition, Template, Column]) -> 'DeleteBuilder':
|
|
1061
1064
|
"""Add a WHERE condition (multiple calls are ANDed together)"""
|
|
1062
1065
|
self._conditions.append(condition)
|
|
1063
1066
|
self._requires_where = False
|
|
@@ -1112,6 +1115,9 @@ class DeleteBuilder(QueryBuilder):
|
|
|
1112
1115
|
for cond in self._conditions:
|
|
1113
1116
|
if isinstance(cond, Template):
|
|
1114
1117
|
where_parts.append(t'({cond})')
|
|
1118
|
+
elif isinstance(cond, Column):
|
|
1119
|
+
col_str = str(cond)
|
|
1120
|
+
where_parts.append(t'{col_str:literal}')
|
|
1115
1121
|
else:
|
|
1116
1122
|
where_parts.append(cond.to_tsql())
|
|
1117
1123
|
combined_where = t_join(t' AND ', where_parts)
|
|
@@ -1210,7 +1216,7 @@ class SelectQueryBuilder(QueryBuilder):
|
|
|
1210
1216
|
self._columns = None
|
|
1211
1217
|
return self
|
|
1212
1218
|
|
|
1213
|
-
def where(self, condition: Union[Condition, Template]) -> 'SelectQueryBuilder':
|
|
1219
|
+
def where(self, condition: Union[Condition, Template, Column]) -> 'SelectQueryBuilder':
|
|
1214
1220
|
"""Add a WHERE condition (multiple calls are ANDed together)
|
|
1215
1221
|
|
|
1216
1222
|
Accepts either Condition objects from query builder or raw t-string Templates
|
|
@@ -1401,6 +1407,9 @@ class SelectQueryBuilder(QueryBuilder):
|
|
|
1401
1407
|
for cond in self._conditions:
|
|
1402
1408
|
if isinstance(cond, Template):
|
|
1403
1409
|
where_parts.append(t'({cond})')
|
|
1410
|
+
elif isinstance(cond, Column):
|
|
1411
|
+
col_str = str(cond)
|
|
1412
|
+
where_parts.append(t'{col_str:literal}')
|
|
1404
1413
|
else:
|
|
1405
1414
|
where_parts.append(cond.to_tsql())
|
|
1406
1415
|
combined_where = t_join(t' AND ', where_parts)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|