33[ ![ 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 )
44![ GitHub repo size] ( https://img.shields.io/github/repo-size/co0lc0der/simple-query-builder-python?label=size&style=flat-square )
55[ ![ 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 )
77![ PyPI] ( https://img.shields.io/pypi/v/simple-query-builder?color=yellow&style=flat-square )
88![ PyPI - Downloads] ( https://img.shields.io/pypi/dm/simple-query-builder?color=darkgreen&style=flat-square )
99
@@ -30,278 +30,33 @@ Or from Github:
3030pip install https://github.com/co0lc0der/simple-query-builder-python/archive/main.zip
3131```
3232## 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-
5433### Import the module and init ` QueryBuilder ` with ` Database() `
5534``` python
5635from simple_query_builder import *
5736
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' )
6338
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: ' )
6641```
6742### Usage examples
68- - Select all rows from a table
43+ #### Select all rows from a table
6944``` python
7045results = qb.select(' users' ).all()
7146```
47+ Result query
7248``` sql
7349SELECT * FROM ` users` ;
7450```
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
8552``` python
8653results = 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()
8954```
55+ Result query
9056``` sql
9157SELECT * FROM ` users` WHERE (` id` > 1 ) AND (` group_id` = 2 );
9258```
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
30560``` python
30661qb.update(' users' , {
30762 ' username' : ' John Doe' ,
@@ -310,72 +65,22 @@ qb.update('users', {
31065 .where([[' id' , ' =' , 7 ]])\
31166 .limit()\
31267 .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()
32168```
69+ Result query
32270``` sql
32371UPDATE ` users` SET ` username` = ' John Doe' , ` status` = ' new status'
32472WHERE ` id` = 7 LIMIT 1 ;
32573```
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