3
3
[ ![ Latest Version] ( https://img.shields.io/github/release/co0lc0der/simple-query-builder-python?color=orange&style=flat-square )] ( https://github.com/co0lc0der/simple-query-builder-python/release )
4
4
![ GitHub repo size] ( https://img.shields.io/github/repo-size/co0lc0der/simple-query-builder-python?label=size&style=flat-square )
5
5
[ ![ GitHub license] ( https://img.shields.io/github/license/co0lc0der/simple-query-builder-python?style=flat-square )] ( https://github.com/co0lc0der/simple-query-builder-python/blob/main/LICENSE.md )
6
- ![ Python 3.7, 3.8, 3.9, 3.10] ( https://img.shields.io/pypi/pyversions/simple-query-builder?color=blueviolet&style=flat-square )
6
+ ![ Python 3.7, 3.8, 3.9, 3.10, 3.11, 3.12 ] ( https://img.shields.io/pypi/pyversions/simple-query-builder?color=blueviolet&style=flat-square )
7
7
![ PyPI] ( https://img.shields.io/pypi/v/simple-query-builder?color=yellow&style=flat-square )
8
8
![ PyPI - Downloads] ( https://img.shields.io/pypi/dm/simple-query-builder?color=darkgreen&style=flat-square )
9
9
@@ -30,278 +30,33 @@ Or from Github:
30
30
pip install https://github.com/co0lc0der/simple-query-builder-python/archive/main.zip
31
31
```
32
32
## How to use
33
- ### Main public methods
34
- - ` get_sql() ` returns SQL query string which will be executed
35
- - ` get_params() ` returns a tuple of parameters for a query
36
- - ` get_result() ` returns query's result
37
- - ` get_count() ` returns result's rows count
38
- - ` get_error() ` returns ` True ` if an error is had
39
- - ` get_error_message() ` returns an error message if an error is had
40
- - ` set_error(message) ` sets ` _error ` to ` True ` and ` _error_message `
41
- - ` get_first() ` returns the first item of results
42
- - ` get_last() ` returns the last item of results
43
- - ` reset() ` resets state to default values
44
- - ` all() ` executes SQL query and returns all rows of result (` fetchall() ` )
45
- - ` one() ` executes SQL query and returns the first row of result (` fetchone() ` )
46
- - ` column(col) ` executes SQL query and returns the needed column of result by its index or name, ` col ` is ` 0 ` by default
47
- - ` pluck(key, col) ` executes SQL query and returns a list of tuples/dicts (the key (usually ID) and the needed column of result) by its indexes or names, ` key ` is ` 0 ` and ` col ` is ` 1 ` by default
48
- - ` go() ` this method is for non ` SELECT ` queries. it executes SQL query and returns nothing (but returns the last inserted row ID for ` INSERT ` method)
49
- - ` exists() ` returns ` True ` if SQL query has a row and ` False ` if it hasn't
50
- - ` count() ` prepares a query with SQL ` COUNT(*) ` function and executes it
51
- - ` query(sql, params, fetch_type, col_index) ` executes prepared ` sql ` with ` params ` , it can be used for custom queries
52
- - 'SQL' methods are presented in [ Usage section] ( #usage-examples )
53
-
54
33
### Import the module and init ` QueryBuilder ` with ` Database() `
55
34
``` python
56
35
from simple_query_builder import *
57
36
58
- # if you want to get results as a list of dictionaries (by default since 0.3.5)
59
- qb = QueryBuilder(DataBase(), ' my_db.db' ) # result_dict=True, print_errors=False
60
-
61
- # or if you want to get results as a list of tuples (since 0.3.5)
62
- qb = QueryBuilder(DataBase(), ' my_db.db' , result_dict = False )
37
+ qb = QueryBuilder(DataBase(), ' my_db.db' )
63
38
64
- # for printing errors into terminal (since 0.3.5)
65
- qb = QueryBuilder(DataBase(), ' my_db.db ' , print_errors = True )
39
+ # or DB in memory
40
+ qb = QueryBuilder(DataBase(), ' :memory: ' )
66
41
```
67
42
### Usage examples
68
- - Select all rows from a table
43
+ #### Select all rows from a table
69
44
``` python
70
45
results = qb.select(' users' ).all()
71
46
```
47
+ Result query
72
48
``` sql
73
49
SELECT * FROM ` users` ;
74
50
```
75
- - Select a row with a condition
76
- ``` python
77
- results = qb.select(' users' ).where([[' id' , ' =' , 10 ]]).one()
78
- # or since 0.3.4
79
- results = qb.select(' users' ).where([[' id' , 10 ]]).one()
80
- ```
81
- ``` sql
82
- SELECT * FROM ` users` WHERE ` id` = 10 ;
83
- ```
84
- - Select rows with two conditions
51
+ #### Select rows with two conditions
85
52
``` python
86
53
results = qb.select(' users' ).where([[' id' , ' >' , 1 ], ' and' , [' group_id' , ' =' , 2 ]]).all()
87
- # or since 0.3.4
88
- results = qb.select(' users' ).where([[' id' , ' >' , 1 ], ' and' , [' group_id' , 2 ]]).all()
89
54
```
55
+ Result query
90
56
``` sql
91
57
SELECT * FROM ` users` WHERE (` id` > 1 ) AND (` group_id` = 2 );
92
58
```
93
- - Select a row with a ` LIKE ` and ` NOT LIKE ` condition
94
- ``` python
95
- results = qb.select(' users' ).like([' name' , ' %John%' ]).all()
96
- # or
97
- results = qb.select(' users' ).where([[' name' , ' LIKE' , ' %John%' ]]).all()
98
- # or since 0.3.5
99
- results = qb.select(' users' ).like(' name' , ' %John%' ).all()
100
- ```
101
- ``` sql
102
- SELECT * FROM ` users` WHERE (` name` LIKE ' %John%' );
103
- ```
104
- ``` python
105
- results = qb.select(' users' ).not_like([' name' , ' %John%' ]).all()
106
- # or
107
- results = qb.select(' users' ).where([[' name' , ' NOT LIKE' , ' %John%' ]]).all()
108
- # or since 0.3.5
109
- results = qb.select(' users' ).not_like(' name' , ' %John%' ).all()
110
- ```
111
- ``` sql
112
- SELECT * FROM ` users` WHERE (` name` NOT LIKE ' %John%' );
113
- ```
114
- - Select a row with a ` IS NULL ` and ` IS NOT NULL ` condition (since 0.3.5)
115
- ``` python
116
- results = qb.select(' users' ).is_null(' phone' ).all()
117
- # or
118
- results = qb.select(' users' ).where([[' phone' , ' is null' ]]).all()
119
- ```
120
- ``` sql
121
- SELECT * FROM ` users` WHERE (` phone` IS NULL );
122
- ```
123
- ``` python
124
- results = qb.select(' customers' ).is_not_null(' address' ).all()
125
- # or
126
- results = qb.select(' customers' ).not_null(' address' ).all()
127
- # or
128
- results = qb.select(' customers' ).where([[' address' , ' is not null' ]]).all()
129
- ```
130
- ``` sql
131
- SELECT * FROM ` customers` WHERE (` address` IS NOT NULL );
132
- ```
133
- - Select rows with ` OFFSET ` and ` LIMIT `
134
- ``` python
135
- results = qb.select(' posts' )\
136
- .where([[' user_id' , ' =' , 3 ]])\
137
- .offset(14 )\
138
- .limit(7 )\
139
- .all()
140
- # or since 0.3.4
141
- results = qb.select(' posts' )\
142
- .where([[' user_id' , 3 ]])\
143
- .offset(14 )\
144
- .limit(7 )\
145
- .all()
146
- ```
147
- ``` sql
148
- SELECT * FROM ` posts` WHERE (` user_id` = 3 ) OFFSET 14 LIMIT 7 ;
149
- ```
150
- - Select custom fields with additional SQL
151
- 1 . ` COUNT() `
152
- ``` python
153
- results = qb.select(' users' , {' counter' : ' COUNT(*)' }).one()
154
- # or
155
- results = qb.count(' users' ).one()
156
- ```
157
- ``` sql
158
- SELECT COUNT (* ) AS ` counter` FROM ` users` ;
159
- ```
160
- 2 . ` ORDER BY `
161
- ``` python
162
- results = qb.select({' b' : ' branches' }, [' b.id' , ' b.name' ])\
163
- .where([[' b.id' , ' >' , 1 ], ' and' , [' b.parent_id' , 1 ]])\
164
- .order_by(' b.id' , ' desc' )\
165
- .all()
166
- # or since 0.3.4
167
- results = qb.select({' b' : ' branches' }, [' b.id' , ' b.name' ])\
168
- .where([[' b.id' , ' >' , 1 ], ' and' , [' b.parent_id' , 1 ]])\
169
- .order_by(' b.id desc' )\
170
- .all()
171
- ```
172
- ``` sql
173
- SELECT ` b` .` id` , ` b` .` name` FROM ` branches` AS ` b`
174
- WHERE (` b` .` id` > 1 ) AND (` b` .` parent_id` = 1 )
175
- ORDER BY ` b` .` id` DESC ;
176
- ```
177
- 3 . ` GROUP BY ` and ` HAVING `
178
- ``` python
179
- results = qb.select(' posts' , [' id' , ' category' , ' title' ])\
180
- .where([[' views' , ' >=' , 1000 ]])\
181
- .group_by(' category' )\
182
- .all()
183
- ```
184
- ``` sql
185
- SELECT ` id` , ` category` , ` title` FROM ` posts`
186
- WHERE (` views` >= 1000 ) GROUP BY ` category` ;
187
- ```
188
- ``` python
189
- groups = qb.select(' orders' , {' month_num' : ' MONTH(`created_at`)' , ' total' : ' SUM(`total`)' })\
190
- .where([[' YEAR(`created_at`)' , ' =' , 2020 ]])\
191
- .group_by(' month_num' )\
192
- .having([[' total' , ' =' , 20000 ]])\
193
- .all()
194
- # or since 0.3.4
195
- groups = qb.select(' orders' , {' month_num' : ' MONTH(`created_at`)' , ' total' : ' SUM(`total`)' })\
196
- .where([[' YEAR(`created_at`)' , 2020 ]])\
197
- .group_by(' month_num' )\
198
- .having([[' total' , 20000 ]])\
199
- .all()
200
- ```
201
- ``` sql
202
- SELECT MONTH(` created_at` ) AS ` month_num` , SUM (` total` ) AS ` total`
203
- FROM ` orders` WHERE (YEAR(` created_at` ) = 2020 )
204
- GROUP BY ` month_num` HAVING (` total` = 20000 );
205
- ```
206
- 4 . ` JOIN ` . Supports ` INNER ` , ` LEFT OUTER ` , ` RIGHT OUTER ` , ` FULL OUTER ` and ` CROSS ` joins (` INNER ` is by default)
207
- ``` python
208
- results = qb.select({' u' : ' users' }, [
209
- ' u.id' ,
210
- ' u.email' ,
211
- ' u.username' ,
212
- {' perms' : ' groups.permissions' }
213
- ])\
214
- .join(' groups' , [' u.group_id' , ' groups.id' ])\
215
- .limit(5 )\
216
- .all()
217
- ```
218
- ``` sql
219
- SELECT ` u` .` id` , ` u` .` email` , ` u` .` username` , ` groups` .` permissions` AS ` perms`
220
- FROM ` users` AS ` u`
221
- INNER JOIN ` groups` ON ` u` .` group_id` = ` groups` .` id`
222
- LIMIT 5 ;
223
- ```
224
- ``` python
225
- results = qb.select({' cp' : ' cabs_printers' }, [
226
- ' cp.id' ,
227
- ' cp.cab_id' ,
228
- {' cab_name' : ' cb.name' },
229
- ' cp.printer_id' ,
230
- {' printer_name' : ' p.name' },
231
- {' cartridge_type' : ' c.name' },
232
- ' cp.comment'
233
- ])\
234
- .join({' cb' : ' cabs' }, [' cp.cab_id' , ' cb.id' ])\
235
- .join({' p' : ' printer_models' }, [' cp.printer_id' , ' p.id' ])\
236
- .join({' c' : ' cartridge_types' }, ' p.cartridge_id=c.id' )\
237
- .where([[' cp.cab_id' , ' in' , [11 , 12 , 13 ]], ' or' , [' cp.cab_id' , ' =' , 5 ], ' and' , [' p.id' , ' >' , ' c.id' ]])\
238
- .all()
239
- ```
240
- ``` sql
241
- SELECT ` cp` .` id` , ` cp` .` cab_id` , ` cb` .` name` AS ` cab_name` , ` cp` .` printer_id` ,
242
- ` p` .` name` AS ` printer_name` , ` c` .` name` AS ` cartridge_type` , ` cp` .` comment`
243
- FROM ` cabs_printers` AS ` cp`
244
- INNER JOIN ` cabs` AS ` cb` ON ` cp` .` cab_id` = ` cb` .` id`
245
- INNER JOIN ` printer_models` AS ` p` ON ` cp` .` printer_id` = ` p` .` id`
246
- INNER JOIN ` cartridge_types` AS ` c` ON p .cartridge_id = c .id
247
- WHERE (` cp` .` cab_id` IN (11 , 12 , 13 )) OR (` cp` .` cab_id` = 5 ) AND (` p` .` id` > ` c` .` id` );
248
- ```
249
- ``` python
250
- # since 0.3.4
251
- results = qb.select({' cp' : ' cabs_printers' }, [
252
- ' cp.id' ,
253
- ' cp.cab_id' ,
254
- {' cab_name' : ' cb.name' },
255
- ' cp.printer_id' ,
256
- {' cartridge_id' : ' c.id' },
257
- {' printer_name' : ' p.name' },
258
- {' cartridge_type' : ' c.name' },
259
- ' cp.comment'
260
- ])\
261
- .join({' cb' : ' cabs' }, [' cp.cab_id' , ' cb.id' ])\
262
- .join({' p' : ' printer_models' }, [' cp.printer_id' , ' p.id' ])\
263
- .join({' c' : ' cartridge_types' }, [' p.cartridge_id' , ' c.id' ])\
264
- .group_by([' cp.printer_id' , ' cartridge_id' ])\
265
- .order_by([' cp.cab_id' , ' cp.printer_id desc' ])\
266
- .all()
267
- ```
268
- ``` sql
269
- SELECT ` cp` .` id` , ` cp` .` cab_id` , ` cb` .` name` AS ` cab_name` , ` cp` .` printer_id` , ` c` .` id` AS ` cartridge_id` ,
270
- ` p` .` name` AS ` printer_name` , ` c` .` name` AS ` cartridge_type` , ` cp` .` comment`
271
- FROM ` cabs_printers` AS ` cp`
272
- INNER JOIN ` cabs` AS ` cb` ON ` cp` .` cab_id` = ` cb` .` id`
273
- INNER JOIN ` printer_models` AS ` p` ON ` cp` .` printer_id` = ` p` .` id`
274
- INNER JOIN ` cartridge_types` AS ` c` ON ` p` .` cartridge_id` = ` c` .` id`
275
- GROUP BY ` cp` .` printer_id` , ` cartridge_id`
276
- ORDER BY ` cp` .` cab_id` ASC , ` cp` .` printer_id` DESC ;
277
- ```
278
- - Insert a row
279
- ``` python
280
- new_id = qb.insert(' groups' , {
281
- ' name' : ' Moderator' ,
282
- ' permissions' : ' moderator'
283
- }).go()
284
- ```
285
- ``` sql
286
- INSERT INTO ` groups` (` name` , ` permissions` ) VALUES (' Moderator' , ' moderator' );
287
- ```
288
- - Insert many rows
289
- ``` python
290
- qb.insert(' groups' , [[' name' , ' role' ],
291
- [' Moderator' , ' moderator' ],
292
- [' Moderator2' , ' moderator' ],
293
- [' User' , ' user' ],
294
- [' User2' , ' user' ]
295
- ]).go()
296
- ```
297
- ``` sql
298
- INSERT INTO ` groups` (` name` , ` role` )
299
- VALUES (' Moderator' , ' moderator' ),
300
- (' Moderator2' , ' moderator' ),
301
- (' User' , ' user' ),
302
- (' User2' , ' user' );
303
- ```
304
- - Update a row
59
+ #### Update a row
305
60
``` python
306
61
qb.update(' users' , {
307
62
' username' : ' John Doe' ,
@@ -310,72 +65,22 @@ qb.update('users', {
310
65
.where([[' id' , ' =' , 7 ]])\
311
66
.limit()\
312
67
.go()
313
- # or since 0.3.4
314
- qb.update(' users' , {
315
- ' username' : ' John Doe' ,
316
- ' status' : ' new status'
317
- })\
318
- .where([[' id' , 7 ]])\
319
- .limit()\
320
- .go()
321
68
```
69
+ Result query
322
70
``` sql
323
71
UPDATE ` users` SET ` username` = ' John Doe' , ` status` = ' new status'
324
72
WHERE ` id` = 7 LIMIT 1 ;
325
73
```
326
- - Update rows
327
- ``` python
328
- qb.update(' posts' , {' status' : ' published' })\
329
- .where([[' YEAR(`updated_at`)' , ' >' , 2020 ]])\
330
- .go()
331
- ```
332
- ``` sql
333
- UPDATE ` posts` SET ` status` = ' published'
334
- WHERE (YEAR(` updated_at` ) > 2020 );
335
- ```
336
- - Delete a row
337
- ``` python
338
- qb.delete(' users' )\
339
- .where([[' name' , ' =' , ' John' ]])\
340
- .limit()\
341
- .go()
342
- # or since 0.3.4
343
- qb.delete(' users' )\
344
- .where([[' name' , ' John' ]])\
345
- .limit()\
346
- .go()
347
- ```
348
- ``` sql
349
- DELETE FROM ` users` WHERE ` name` = ' John' LIMIT 1 ;
350
- ```
351
- - Delete rows
352
- ``` python
353
- qb.delete(' comments' )\
354
- .where([[' user_id' , ' =' , 10 ]])\
355
- .go()
356
- # or since 0.3.4
357
- qb.delete(' comments' )\
358
- .where([[' user_id' , 10 ]])\
359
- .go()
360
- ```
361
- ``` sql
362
- DELETE FROM ` comments` WHERE ` user_id` = 10 ;
363
- ```
364
- - Truncate a table
365
-
366
- This method will be moved to another class
367
- ``` python
368
- qb.truncate(' users' ).go()
369
- ```
370
- ``` sql
371
- TRUNCATE TABLE ` users` ;
372
- ```
373
- - Drop a table
374
-
375
- This method will be moved to another class
376
- ``` python
377
- qb.drop(' temporary' ).go()
378
- ```
379
- ``` sql
380
- DROP TABLE IF EXISTS ` temporary` ;
381
- ```
74
+ More examples you can find in [ documentation] ( https://github.com/co0lc0der/simple-query-builder-python/blob/main/docs/index.md )
75
+
76
+ ## ToDo
77
+ I'm going to add the next features into future versions
78
+ - write more unit testes
79
+ - add subqueries for QueryBuilder
80
+ - add ` BETWEEN `
81
+ - add ` WHERE EXISTS `
82
+ - add TableBuilder class (for beginning ` CREATE TABLE ` , move ` qb.drop() ` and ` qb.truncate() ` into it)
83
+ - add MySQL support
84
+ - add PostgreSQL support
85
+ - add ` WITH `
86
+ - and probably something more
0 commit comments