t-sql 4.7.0__tar.gz → 4.7.1__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.7.0/README.md → t_sql-4.7.1/PKG-INFO +26 -0
- t_sql-4.7.0/PKG-INFO → t_sql-4.7.1/README.md +16 -10
- {t_sql-4.7.0 → t_sql-4.7.1}/pyproject.toml +1 -1
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_deep_nesting.py +2 -1
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_tsql.py +15 -4
- {t_sql-4.7.0 → t_sql-4.7.1}/tsql/__init__.py +3 -2
- {t_sql-4.7.0 → t_sql-4.7.1}/.dockerignore +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/.github/workflows/publish.yml +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/.github/workflows/test.yml +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/.gitignore +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/Dockerfile +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/LICENSE +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/compose.yaml +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/context7.json +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/pytest.ini +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_alembic_integration.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_asyncpg_integration.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_different_object_types.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_error_messages.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_escaped.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_escaped_binary_hex.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_helper_functions.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_injection_edge_cases.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_injection_protection_validation.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_injections_for_escaped.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_mysql_integration.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_parameter_names.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_query_builder.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_sqlalchemy_integration.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_sqlite_integration.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_string_based_builders.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_styles.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_template_in_builders.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tests/test_type_processor.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tsql/query_builder.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tsql/row.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tsql/styles.py +0 -0
- {t_sql-4.7.0 → t_sql-4.7.1}/tsql/type_processor.py +0 -0
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: t-sql
|
|
3
|
+
Version: 4.7.1
|
|
4
|
+
Summary: Safe SQL. SQL queries for python t-strings (PEP 750)
|
|
5
|
+
Project-URL: Homepage, https://github.com/nhumrich/t-sql
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Python: >=3.14
|
|
8
|
+
Requires-Dist: alembic>=1.17.0
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
1
11
|
# t-sql
|
|
2
12
|
|
|
3
13
|
A lightweight SQL templating library that leverages Python 3.14's t-strings (PEP 750).
|
|
@@ -105,6 +115,22 @@ sql, params = tsql.render(t"UPDATE users SET {values:as_set} WHERE id='abc123'")
|
|
|
105
115
|
# ('UPDATE users SET name = ?, email = ? WHERE id='abc123'', ['joe', 'joe@example.com'])
|
|
106
116
|
```
|
|
107
117
|
|
|
118
|
+
#### Tuples for IN clauses
|
|
119
|
+
|
|
120
|
+
Use tuples to expand lists of values for SQL IN clauses:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
# Convert list to tuple for IN clause
|
|
124
|
+
my_ids = ['123', '234', '531']
|
|
125
|
+
sql, params = tsql.render(t"SELECT * FROM mytable WHERE id IN {tuple(my_ids)}")
|
|
126
|
+
# ('SELECT * FROM mytable WHERE id IN (?, ?, ?)', ['123', '234', '531'])
|
|
127
|
+
|
|
128
|
+
# Or use a tuple directly
|
|
129
|
+
active_statuses = ('active', 'pending', 'approved')
|
|
130
|
+
sql, params = tsql.render(t"SELECT * FROM orders WHERE status IN {active_statuses}")
|
|
131
|
+
# ('SELECT * FROM orders WHERE status IN (?, ?, ?)', ['active', 'pending', 'approved'])
|
|
132
|
+
```
|
|
133
|
+
|
|
108
134
|
### Helper Functions
|
|
109
135
|
|
|
110
136
|
t-sql provides several convenience functions for common SQL operations:
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: t-sql
|
|
3
|
-
Version: 4.7.0
|
|
4
|
-
Summary: Safe SQL. SQL queries for python t-strings (PEP 750)
|
|
5
|
-
Project-URL: Homepage, https://github.com/nhumrich/t-sql
|
|
6
|
-
License-File: LICENSE
|
|
7
|
-
Requires-Python: >=3.14
|
|
8
|
-
Requires-Dist: alembic>=1.17.0
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
|
|
11
1
|
# t-sql
|
|
12
2
|
|
|
13
3
|
A lightweight SQL templating library that leverages Python 3.14's t-strings (PEP 750).
|
|
@@ -115,6 +105,22 @@ sql, params = tsql.render(t"UPDATE users SET {values:as_set} WHERE id='abc123'")
|
|
|
115
105
|
# ('UPDATE users SET name = ?, email = ? WHERE id='abc123'', ['joe', 'joe@example.com'])
|
|
116
106
|
```
|
|
117
107
|
|
|
108
|
+
#### Tuples for IN clauses
|
|
109
|
+
|
|
110
|
+
Use tuples to expand lists of values for SQL IN clauses:
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
# Convert list to tuple for IN clause
|
|
114
|
+
my_ids = ['123', '234', '531']
|
|
115
|
+
sql, params = tsql.render(t"SELECT * FROM mytable WHERE id IN {tuple(my_ids)}")
|
|
116
|
+
# ('SELECT * FROM mytable WHERE id IN (?, ?, ?)', ['123', '234', '531'])
|
|
117
|
+
|
|
118
|
+
# Or use a tuple directly
|
|
119
|
+
active_statuses = ('active', 'pending', 'approved')
|
|
120
|
+
sql, params = tsql.render(t"SELECT * FROM orders WHERE status IN {active_statuses}")
|
|
121
|
+
# ('SELECT * FROM orders WHERE status IN (?, ?, ?)', ['active', 'pending', 'approved'])
|
|
122
|
+
```
|
|
123
|
+
|
|
118
124
|
### Helper Functions
|
|
119
125
|
|
|
120
126
|
t-sql provides several convenience functions for common SQL operations:
|
|
@@ -311,7 +311,8 @@ def test_case_expression_with_subqueries():
|
|
|
311
311
|
|
|
312
312
|
sql, params = tsql.render(query, style=styles.QMARK)
|
|
313
313
|
|
|
314
|
-
assert "CASE
|
|
314
|
+
assert "CASE" in sql
|
|
315
|
+
assert "WHEN (SELECT COUNT(*)" in sql
|
|
315
316
|
assert "> ?" in sql
|
|
316
317
|
assert "THEN 'active'" in sql
|
|
317
318
|
assert params == [10]
|
|
@@ -35,15 +35,26 @@ def test_merges_literals_using_exsiting_tstring():
|
|
|
35
35
|
assert result._sql == 'hello there'
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
def
|
|
39
|
-
|
|
38
|
+
def test_strips_horizontal_whitespace():
|
|
39
|
+
# Horizontal whitespace (spaces/tabs) is collapsed, but newlines are preserved
|
|
40
|
+
result = tsql.render(t"SELECT * FROM table")
|
|
40
41
|
assert result[0] == 'SELECT * FROM table'
|
|
41
42
|
|
|
42
43
|
|
|
44
|
+
def test_preserves_newlines_for_sql_comments():
|
|
45
|
+
# Newlines must be preserved so -- style SQL comments work correctly
|
|
46
|
+
query = t"""SELECT * FROM users
|
|
47
|
+
-- Filter by active status
|
|
48
|
+
WHERE active = true"""
|
|
49
|
+
result = tsql.render(query)
|
|
50
|
+
assert '-- Filter by active status\n' in result[0]
|
|
51
|
+
assert 'WHERE active = true' in result[0]
|
|
52
|
+
|
|
53
|
+
|
|
43
54
|
def test_doesnt_strip_whitespace_in_values():
|
|
44
55
|
user_input = 'Some string\nWith whitespace. With Formating that is \n just right'
|
|
45
|
-
result = tsql.render(t'INSERT
|
|
46
|
-
assert result[0] ==
|
|
56
|
+
result = tsql.render(t'INSERT INTO table (vals) VALUES({user_input})')
|
|
57
|
+
assert result[0] == 'INSERT INTO table (vals) VALUES(?)'
|
|
47
58
|
assert result[1] == [user_input]
|
|
48
59
|
|
|
49
60
|
|
|
@@ -9,8 +9,9 @@ from tsql.styles import ParamStyle, QMARK
|
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__name__)
|
|
11
11
|
|
|
12
|
-
# Pre-compile regex for whitespace collapsing
|
|
13
|
-
|
|
12
|
+
# Pre-compile regex for horizontal whitespace collapsing (spaces/tabs only)
|
|
13
|
+
# Preserves newlines so that -- style SQL comments work correctly
|
|
14
|
+
_WHITESPACE_RE = re.compile(r'[ \t]+')
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
16
17
|
from tsql.query_builder import QueryBuilder
|
|
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
|