namedquery 0.1.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.
- namedquery-0.1.0/LICENSE +21 -0
- namedquery-0.1.0/PKG-INFO +143 -0
- namedquery-0.1.0/README.md +103 -0
- namedquery-0.1.0/namedquery/__init__.py +2 -0
- namedquery-0.1.0/namedquery/core.py +20 -0
- namedquery-0.1.0/namedquery.egg-info/PKG-INFO +143 -0
- namedquery-0.1.0/namedquery.egg-info/SOURCES.txt +10 -0
- namedquery-0.1.0/namedquery.egg-info/dependency_links.txt +1 -0
- namedquery-0.1.0/namedquery.egg-info/top_level.txt +1 -0
- namedquery-0.1.0/pyproject.toml +28 -0
- namedquery-0.1.0/setup.cfg +4 -0
- namedquery-0.1.0/tests/test_namedquery.py +19 -0
namedquery-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gustavo Venturini
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: namedquery
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Named SQL parameters with once-at-definition parsing
|
|
5
|
+
Author-email: Gustavo Venturini <gustavo.c.venturini@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Gustavo Venturini
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/vottini/namedquery
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Operating System :: OS Independent
|
|
33
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
34
|
+
Classifier: Topic :: Database
|
|
35
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
36
|
+
Requires-Python: >=3.11
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
License-File: LICENSE
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# namedquery
|
|
43
|
+
|
|
44
|
+
A minimal Python utility that converts named SQL parameters (`:name` style) into
|
|
45
|
+
positional `$N` parameters, parsing the query once at definition time so repeated
|
|
46
|
+
executions pay no parsing cost.
|
|
47
|
+
|
|
48
|
+
> Most named-parameter libraries re-parse the SQL string on every call. `namedquery`
|
|
49
|
+
> exists because that's unnecessary work — if your queries are fixed at startup,
|
|
50
|
+
> the regex should run exactly once. Every subsequent execution is just a list lookup.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install namedquery
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Why
|
|
63
|
+
|
|
64
|
+
Most Python SQL drivers that target PostgreSQL (`asyncpg`, `psycopg3`) expect
|
|
65
|
+
positional parameters (`$1`, `$2`, …), but writing positional SQL by hand is
|
|
66
|
+
error-prone — parameter order must match the argument list exactly.
|
|
67
|
+
|
|
68
|
+
Named parameters (`:id`, `:active`) are readable and order-independent, but need
|
|
69
|
+
to be converted before the driver sees them.
|
|
70
|
+
|
|
71
|
+
`namedquery` does that conversion **once**, at the time you define the query. Every
|
|
72
|
+
subsequent execution is a plain list lookup — no regex, no re-parsing.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from namedquery import named
|
|
80
|
+
|
|
81
|
+
GET_USER = named("SELECT * FROM users WHERE id = :id AND active = :active")
|
|
82
|
+
|
|
83
|
+
# Transformed SQL, ready for the driver
|
|
84
|
+
GET_USER.sql
|
|
85
|
+
# 'SELECT * FROM users WHERE id = $1 AND active = $2'
|
|
86
|
+
|
|
87
|
+
# Arguments in the correct positional order
|
|
88
|
+
GET_USER.args({'id': 7, 'active': True})
|
|
89
|
+
# [7, True]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Pass directly to your driver:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
await conn.fetch(GET_USER.sql, *GET_USER.args({'id': 7, 'active': True}))
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Defining queries at startup
|
|
99
|
+
|
|
100
|
+
The intended pattern is to define all queries once as module-level constants and
|
|
101
|
+
reuse them throughout the application lifetime:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# queries.py
|
|
105
|
+
from namedquery import named
|
|
106
|
+
|
|
107
|
+
GET_USER = named("SELECT * FROM users WHERE id = :id")
|
|
108
|
+
LIST_ACTIVE = named("SELECT * FROM users WHERE active = :active ORDER BY :order_by")
|
|
109
|
+
INSERT_USER = named("INSERT INTO users (name, email) VALUES (:name, :email) RETURNING id")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### PostgreSQL cast syntax
|
|
113
|
+
|
|
114
|
+
`::type` casts are left untouched:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
named("SELECT col::text FROM t WHERE id = :id").sql
|
|
118
|
+
# 'SELECT col::text FROM t WHERE id = $1'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## API
|
|
124
|
+
|
|
125
|
+
### `named(sql) -> NamedQuery`
|
|
126
|
+
|
|
127
|
+
Parses `sql`, replaces every `:name` placeholder with a `$N` positional parameter,
|
|
128
|
+
and returns a `NamedQuery` instance.
|
|
129
|
+
|
|
130
|
+
### `NamedQuery.sql`
|
|
131
|
+
|
|
132
|
+
The transformed SQL string with `$N` placeholders. Pass this to your driver.
|
|
133
|
+
|
|
134
|
+
### `NamedQuery.args(kwargs) -> list`
|
|
135
|
+
|
|
136
|
+
Returns the values from `kwargs` in the order the corresponding parameters appear
|
|
137
|
+
in the SQL. Pass the result as positional arguments to your driver call.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
|
|
2
|
+
# namedquery
|
|
3
|
+
|
|
4
|
+
A minimal Python utility that converts named SQL parameters (`:name` style) into
|
|
5
|
+
positional `$N` parameters, parsing the query once at definition time so repeated
|
|
6
|
+
executions pay no parsing cost.
|
|
7
|
+
|
|
8
|
+
> Most named-parameter libraries re-parse the SQL string on every call. `namedquery`
|
|
9
|
+
> exists because that's unnecessary work — if your queries are fixed at startup,
|
|
10
|
+
> the regex should run exactly once. Every subsequent execution is just a list lookup.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install namedquery
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Why
|
|
23
|
+
|
|
24
|
+
Most Python SQL drivers that target PostgreSQL (`asyncpg`, `psycopg3`) expect
|
|
25
|
+
positional parameters (`$1`, `$2`, …), but writing positional SQL by hand is
|
|
26
|
+
error-prone — parameter order must match the argument list exactly.
|
|
27
|
+
|
|
28
|
+
Named parameters (`:id`, `:active`) are readable and order-independent, but need
|
|
29
|
+
to be converted before the driver sees them.
|
|
30
|
+
|
|
31
|
+
`namedquery` does that conversion **once**, at the time you define the query. Every
|
|
32
|
+
subsequent execution is a plain list lookup — no regex, no re-parsing.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from namedquery import named
|
|
40
|
+
|
|
41
|
+
GET_USER = named("SELECT * FROM users WHERE id = :id AND active = :active")
|
|
42
|
+
|
|
43
|
+
# Transformed SQL, ready for the driver
|
|
44
|
+
GET_USER.sql
|
|
45
|
+
# 'SELECT * FROM users WHERE id = $1 AND active = $2'
|
|
46
|
+
|
|
47
|
+
# Arguments in the correct positional order
|
|
48
|
+
GET_USER.args({'id': 7, 'active': True})
|
|
49
|
+
# [7, True]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Pass directly to your driver:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
await conn.fetch(GET_USER.sql, *GET_USER.args({'id': 7, 'active': True}))
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Defining queries at startup
|
|
59
|
+
|
|
60
|
+
The intended pattern is to define all queries once as module-level constants and
|
|
61
|
+
reuse them throughout the application lifetime:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
# queries.py
|
|
65
|
+
from namedquery import named
|
|
66
|
+
|
|
67
|
+
GET_USER = named("SELECT * FROM users WHERE id = :id")
|
|
68
|
+
LIST_ACTIVE = named("SELECT * FROM users WHERE active = :active ORDER BY :order_by")
|
|
69
|
+
INSERT_USER = named("INSERT INTO users (name, email) VALUES (:name, :email) RETURNING id")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### PostgreSQL cast syntax
|
|
73
|
+
|
|
74
|
+
`::type` casts are left untouched:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
named("SELECT col::text FROM t WHERE id = :id").sql
|
|
78
|
+
# 'SELECT col::text FROM t WHERE id = $1'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## API
|
|
84
|
+
|
|
85
|
+
### `named(sql) -> NamedQuery`
|
|
86
|
+
|
|
87
|
+
Parses `sql`, replaces every `:name` placeholder with a `$N` positional parameter,
|
|
88
|
+
and returns a `NamedQuery` instance.
|
|
89
|
+
|
|
90
|
+
### `NamedQuery.sql`
|
|
91
|
+
|
|
92
|
+
The transformed SQL string with `$N` placeholders. Pass this to your driver.
|
|
93
|
+
|
|
94
|
+
### `NamedQuery.args(kwargs) -> list`
|
|
95
|
+
|
|
96
|
+
Returns the values from `kwargs` in the order the corresponding parameters appear
|
|
97
|
+
in the SQL. Pass the result as positional arguments to your driver call.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
_named_param_re = re.compile(r'(?<!:):(\w+)')
|
|
4
|
+
|
|
5
|
+
class NamedQuery:
|
|
6
|
+
def __init__(self, sql):
|
|
7
|
+
params = []
|
|
8
|
+
def replace(m):
|
|
9
|
+
params.append(m.group(1))
|
|
10
|
+
return f'${len(params)}'
|
|
11
|
+
|
|
12
|
+
self.sql = _named_param_re.sub(replace, sql)
|
|
13
|
+
self.params = params
|
|
14
|
+
|
|
15
|
+
def args(self, kwargs):
|
|
16
|
+
return [kwargs[p] for p in self.params]
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def named(sql):
|
|
20
|
+
return NamedQuery(sql)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: namedquery
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Named SQL parameters with once-at-definition parsing
|
|
5
|
+
Author-email: Gustavo Venturini <gustavo.c.venturini@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Gustavo Venturini
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/vottini/namedquery
|
|
29
|
+
Classifier: Development Status :: 4 - Beta
|
|
30
|
+
Classifier: Intended Audience :: Developers
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Operating System :: OS Independent
|
|
33
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
34
|
+
Classifier: Topic :: Database
|
|
35
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
36
|
+
Requires-Python: >=3.11
|
|
37
|
+
Description-Content-Type: text/markdown
|
|
38
|
+
License-File: LICENSE
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# namedquery
|
|
43
|
+
|
|
44
|
+
A minimal Python utility that converts named SQL parameters (`:name` style) into
|
|
45
|
+
positional `$N` parameters, parsing the query once at definition time so repeated
|
|
46
|
+
executions pay no parsing cost.
|
|
47
|
+
|
|
48
|
+
> Most named-parameter libraries re-parse the SQL string on every call. `namedquery`
|
|
49
|
+
> exists because that's unnecessary work — if your queries are fixed at startup,
|
|
50
|
+
> the regex should run exactly once. Every subsequent execution is just a list lookup.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install namedquery
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Why
|
|
63
|
+
|
|
64
|
+
Most Python SQL drivers that target PostgreSQL (`asyncpg`, `psycopg3`) expect
|
|
65
|
+
positional parameters (`$1`, `$2`, …), but writing positional SQL by hand is
|
|
66
|
+
error-prone — parameter order must match the argument list exactly.
|
|
67
|
+
|
|
68
|
+
Named parameters (`:id`, `:active`) are readable and order-independent, but need
|
|
69
|
+
to be converted before the driver sees them.
|
|
70
|
+
|
|
71
|
+
`namedquery` does that conversion **once**, at the time you define the query. Every
|
|
72
|
+
subsequent execution is a plain list lookup — no regex, no re-parsing.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from namedquery import named
|
|
80
|
+
|
|
81
|
+
GET_USER = named("SELECT * FROM users WHERE id = :id AND active = :active")
|
|
82
|
+
|
|
83
|
+
# Transformed SQL, ready for the driver
|
|
84
|
+
GET_USER.sql
|
|
85
|
+
# 'SELECT * FROM users WHERE id = $1 AND active = $2'
|
|
86
|
+
|
|
87
|
+
# Arguments in the correct positional order
|
|
88
|
+
GET_USER.args({'id': 7, 'active': True})
|
|
89
|
+
# [7, True]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Pass directly to your driver:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
await conn.fetch(GET_USER.sql, *GET_USER.args({'id': 7, 'active': True}))
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Defining queries at startup
|
|
99
|
+
|
|
100
|
+
The intended pattern is to define all queries once as module-level constants and
|
|
101
|
+
reuse them throughout the application lifetime:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# queries.py
|
|
105
|
+
from namedquery import named
|
|
106
|
+
|
|
107
|
+
GET_USER = named("SELECT * FROM users WHERE id = :id")
|
|
108
|
+
LIST_ACTIVE = named("SELECT * FROM users WHERE active = :active ORDER BY :order_by")
|
|
109
|
+
INSERT_USER = named("INSERT INTO users (name, email) VALUES (:name, :email) RETURNING id")
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### PostgreSQL cast syntax
|
|
113
|
+
|
|
114
|
+
`::type` casts are left untouched:
|
|
115
|
+
|
|
116
|
+
```python
|
|
117
|
+
named("SELECT col::text FROM t WHERE id = :id").sql
|
|
118
|
+
# 'SELECT col::text FROM t WHERE id = $1'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## API
|
|
124
|
+
|
|
125
|
+
### `named(sql) -> NamedQuery`
|
|
126
|
+
|
|
127
|
+
Parses `sql`, replaces every `:name` placeholder with a `$N` positional parameter,
|
|
128
|
+
and returns a `NamedQuery` instance.
|
|
129
|
+
|
|
130
|
+
### `NamedQuery.sql`
|
|
131
|
+
|
|
132
|
+
The transformed SQL string with `$N` placeholders. Pass this to your driver.
|
|
133
|
+
|
|
134
|
+
### `NamedQuery.args(kwargs) -> list`
|
|
135
|
+
|
|
136
|
+
Returns the values from `kwargs` in the order the corresponding parameters appear
|
|
137
|
+
in the SQL. Pass the result as positional arguments to your driver call.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
namedquery
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
[build-system]
|
|
3
|
+
requires = ["setuptools"]
|
|
4
|
+
build-backend = "setuptools.build_meta"
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "namedquery"
|
|
8
|
+
version = "0.1.0"
|
|
9
|
+
description = "Named SQL parameters with once-at-definition parsing"
|
|
10
|
+
authors = [
|
|
11
|
+
{ name = "Gustavo Venturini", email = "gustavo.c.venturini@gmail.com" }
|
|
12
|
+
]
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
dependencies = []
|
|
15
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
16
|
+
license = {file = "LICENSE"}
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
23
|
+
"Topic :: Database",
|
|
24
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
"Homepage" = "https://github.com/vottini/namedquery"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from namedquery import NamedQuery, named
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def testNamedQuery():
|
|
5
|
+
q = named("SELECT * FROM t WHERE a = :a AND b = :b")
|
|
6
|
+
assert q.sql == "SELECT * FROM t WHERE a = $1 AND b = $2"
|
|
7
|
+
assert q.args({'a': 1, 'b': 2}) == [1, 2]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def testNamedQueryRepeatedParam():
|
|
11
|
+
q = named("SELECT :x + :x AS double")
|
|
12
|
+
assert q.sql == "SELECT $1 + $2 AS double"
|
|
13
|
+
assert q.args({'x': 5}) == [5, 5]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def testNamedQueryCastNotAffected():
|
|
17
|
+
q = named("SELECT col::text FROM t WHERE id = :id")
|
|
18
|
+
assert q.sql == "SELECT col::text FROM t WHERE id = $1"
|
|
19
|
+
assert q.args({'id': 42}) == [42]
|