SQLPuzzle documentation¶
Library for ease of writing SQL queries. For now only for database MySQL & PostgreSQL.
Installation¶
pip install sqlpuzzle
Documentation¶
Note there are also camelCase methods which are only aliases to methods described here. It’s only for backward compatiblity with version 0.x. It will be removed one day.
To all methods you can pass arguments of different types. I know, in this
is
line saying There should be one– and preferably only one –obvious way to do it.
but you can have different type of data for different type of SQL and why to
support only one style and force user to deal with it everywhere.
So you should note that you can:
- Pass single argument. For example for table, column, …
>>> sqlpuzzle.select('column').from_('table') <Select: SELECT "column" FROM "table">
- Pass several arguments. Where you can pass only one argument, most of there time you can also pass several arguments.
>>> sqlpuzzle.select('c1', 'c2').from_('t1', 't2') <Select: SELECT "c1", "c2" FROM "t1", "t2">
- Pass
tuple
orlist
. Because you want for example make aliases. Advantage oftuple
is that you can pass it only when you need alias.>>> sqlpuzzle.select('c1', 'c2').from_('t', ('t', 't2')) <Select: SELECT "c1", "c2" FROM "t", "t" AS "t2">
- Pass
dict
. Because it’s more sexy than tuples. Usage is same. You just have to be aware thatdict
is not sorted, so if you need same order, useOrderedDict
instead. And also with same key you can have only one value.>>> sqlpuzzle.select('c').from_('t').where({'x': 1, 'y': 2}) <Select: SELECT "c" FROM "t" WHERE "x" = 1 AND "y" = 2>
- Pass named arugments. Which is same as
dict
above.>>> sqlpuzzle.select('c').from_('t').where(x=1, y=2) <Select: SELECT "c" FROM "t" WHERE "x" = 1 AND "y" = 2>
Configuration¶
-
sqlpuzzle.
configure
(database)[source]¶ By default sqlpuzzle generates syntax in plain SQL. If you want to change it, you should call this method somewhere on start of your app. For now there is only support of SQLite, MySQL and PostgreSQL.
configure('sqlite') # or configure('mysql') # or configure('postgresql')
Base methods¶
-
sqlpuzzle.
select
(*args, **kwds)[source]¶ Returns
Select
instance and passed arguments are used for list of columns.
-
sqlpuzzle.
select_from
(*args, **kwds)[source]¶ Returns
Select
instance and passed arguments are used for list of tables. Columns are set to *.
-
sqlpuzzle.
insert
()[source]¶ Returns
Insert
instance. But probably you want to useinsert_into()
instead.
-
sqlpuzzle.
insert_into
(table)[source]¶ Returns
Insert
instance and passed argument is used for table.
-
sqlpuzzle.
delete
(*tables)[source]¶ Returns
Delete
instance and passed arguments are used for list of tables from which really data should be deleted. But probably you want to usedelete_from()
instead.
Helpers¶
-
sqlpuzzle.
Q
(*args, **kwds)[source]¶ Use as condition (where, having, …) and pass it to condition. Works like Q object in Django, so you can use it with logical operands (& and |).
sqlpuzzle.where(Q(name='Michael', country=None) | Q(name='Alan'))
-
sqlpuzzle.
C
(string='')¶ Or
sqlpuzzle.customsql
.Force custom SQL if it’s not supported by
sqlpuzzle
.>>> sqlpuzzle.select(sqlpuzzle.C('IFNULL(col, 42) AS col')) <Select: SELECT IFNULL(col, 42) AS col> >>> sqlpuzzle.update('t').set(sqlpuzzle.C('`age` = `age` + 1')).where(id=42) <Update: UPDATE "t" SET `age` = `age` + 1 WHERE "id" = 42>
-
sqlpuzzle.
V
(value)¶ Or
sqlpuzzle.sqlvalue
.SQL values which are escaped. Like values in conditions. SqlPuzzle by default behave to some arguments automatically as SQL value and to some as SQL reference. Use this when SqlPuzzle uses SQL reference instead of value.
>>> sqlpuzzle.select('a') <Select: SELECT `a`> >>> sqlpuzzle.select(sqlpuzzle.V('a')) <Select: SELECT 'a'>
-
sqlpuzzle.
R
(value)¶ Or
sqlpuzzle.sqlreference
.SQL reference is some column. SqlPuzzle by default behave to some arguments automatically as SQL value and to some as SQL reference. Use this when SqlPuzzle uses SQL value instead of reference.
>>> sqlpuzzle.select_from('t').where(name='surname') <Select: SELECT * FROM `t` WHERE `name` = 'surname'> >>> sqlpuzzle.select_from('t').where(name=sqlpuzzle.R('surname')) <Select: SELECT * FROM `t` WHERE `name` = `surname`>
Functions¶
-
sqlpuzzle.
group_concat
(*expr)[source]¶ Function
GROUP_CONCAT(expr [ORDER BY [SEPARATOR]])
Returns: GroupConcat
Relations¶
Use relations in conditions. For example:
>>> sqlpuzzle.select_from('t').where(name=sqlpuzzle.relations.LIKE('M%'))
<Select: SELECT * FROM "t" WHERE "name" LIKE 'M%'>
-
sqlpuzzle.relations.
EQUAL_TO
¶ alias of
sqlpuzzle.relations.EQ
-
sqlpuzzle.relations.
GRATHER_THAN
¶ alias of
sqlpuzzle.relations.GT
-
sqlpuzzle.relations.
GRATHER_THAN_OR_EQUAL_TO
¶ alias of
sqlpuzzle.relations.GE
-
class
sqlpuzzle.relations.
IN
(*args)[source]¶ Relation
IN
.If you pass
None
in list, it will behave correctly:>>> sqlpuzzle.select_from('t').where(col=sqlpuzzle.relations.IN([1,2,None])) <Select: SELECT * FROM "t" WHERE ("col" IN (1, 2) OR "col" IS NULL)>
-
sqlpuzzle.relations.
LESS_THAN
¶ alias of
sqlpuzzle.relations.LT
-
sqlpuzzle.relations.
LESS_THAN_OR_EQUAL_TO
¶ alias of
sqlpuzzle.relations.LE
-
sqlpuzzle.relations.
NOT_EQUAL_TO
¶ alias of
sqlpuzzle.relations.NE
-
class
sqlpuzzle.relations.
NOT_IN
(*args)[source]¶ Relation
NOT IN
.If you pass
None
in list, it will behave correctly:>>> sqlpuzzle.select_from('t').where(col=sqlpuzzle.relations.NOT_IN([1,2,None])) <Select: SELECT * FROM "t" WHERE ("col" NOT IN (1, 2) AND "col" IS NOT NULL)>
Changed in version 1.7.0: There was bug that it generated
("col" NOT IN (1, 2) OR "col" IS NULL)
instead of correct condition.
Select¶
-
class
sqlpuzzle._queries.select.
Select
(*args, **kwds)[source]¶ Examples:
>>> sql = sqlpuzzle.select('id', 'name') >>> sql.from_('user') >>> sql.join('address').on('address.user_id', 'user.id') >>> sql.where({'user.name': sqlpuzzle.relations.LIKE('%Al%'), 'address.city': 'Prague'}) >>> sql.group_by('user.id') >>> sql.order_by('user.name', ('user.sallary', 'desc')) >>> sql.limit(20) <Select: SELECT "id", "name" FROM "user" JOIN "address" ON "address"."user_id" = "user"."id" WHERE "address"."city" = 'Prague' AND "user"."name" LIKE '%Al%' GROUP BY "user"."id" ORDER BY "user"."name", "user"."sallary" DESC LIMIT 20 > >>> sqlpuzzle.select('name').from_(sql).where( <Select: SELECT "name" FROM (...)>
-
__and__
(other)[source]¶ Returns
sqlpuzzle._queries.union.Union
instance,UNION ALL
.>>> sqlpuzzle.select('t') & sqlpuzzle.select('u') <Union: SELECT "t" UNION ALL SELECT "u">
-
__or__
(other)[source]¶ Returns
sqlpuzzle._queries.union.Union
instance,UNION
.>>> sqlpuzzle.select('t') | sqlpuzzle.select('u') <Union: SELECT "t" UNION SELECT "u">
-
from_tables
(*args, **kwds)¶
-
group_by
(*args, **kwds)[source]¶ Default ordering is
ASC
.group_by
acceptdict
as you would expect, but note thatdict
does not have same order. Same for named arguments.>>> sqlpuzzle.select('c').from_('t').group_by('a', ('b', 'desc')) <Select: SELECT "c" FROM "t" GROUP BY "a", "b" DESC>
-
has
(querypart_name, value=None)[source]¶ Returns
True
ifquerypart_name
withvalue
is set. For example you can check if you already used condition bysql.has('where')
.If you want to check for more information, for example if that condition also contain ID, you can do this by
sql.has('where', 'id')
.
-
Union¶
-
class
sqlpuzzle._queries.union.
Union
(query1, query2, union_type='UNION')[source]¶ Class representing
UNION
orUNION ALL
.You will get it by calling magic methods on
Select
:>>> sqlpuzzle.select('t') & sqlpuzzle.select('u') <Union: SELECT "t" UNION ALL SELECT "u"> >>> sqlpuzzle.select('t') | sqlpuzzle.select('u') <Union: SELECT "t" UNION SELECT "u">
-
__and__
(other)[source]¶ Returns
sqlpuzzle._queries.union.Union
instance,UNION ALL
.>>> sqlpuzzle.select('t') & sqlpuzzle.select('u') & sqlpuzzle.select('v') <Union: SELECT "t" UNION ALL SELECT "u" UNION ALL SELECT "v">
-
__or__
(other)[source]¶ Returns
sqlpuzzle._queries.union.Union
instance,UNION
.>>> sqlpuzzle.select('t') | sqlpuzzle.select('u') | sqlpuzzle.select('v') <Union: SELECT "t" UNION SELECT "u" UNION SELECT "v">
-
Insert¶
Update¶
-
class
sqlpuzzle._queries.update.
Update
(table=None)[source]¶ Example:
>>> sqlpuzzle.update('t').set(name='Alan', sallary=12345.67).where(id=1) <Update: UPDATE "t" SET "name" = 'Alan', "sallary" = 12345.67000 WHERE "id" = 1>
-
allow_update_all
()[source]¶ Allow query without
WHERE
condition.By default update without condition will raise exception
ConfirmUpdateAllException
. If you want really update all rows without condition, allow it by calling this method.>>> sqlpuzzle.update('t') Traceback (most recent call last): ... ConfirmUpdateAllException: Are you sure, that you want update all records? >>> sqlpuzzle.update('t').set(a=1).allow_update_all() <Update: UPDATE "t" SET "a" = 1>
-
forbid_update_all
()[source]¶ Forbid query without WHERE condition.
By default update without condition will raise exception
ConfirmUpdateAllException
. It can be allowed by calling methodallow_update_all()
. If you want to again forbid it, call this method.
-
Delete¶
-
class
sqlpuzzle._queries.delete.
Delete
(*tables)[source]¶ Example:
>>> sqlpuzzle.delete_from('t').where(id=1) <Delete: DELETE FROM "t" WHERE "id" = 1>
-
allow_delete_all
()[source]¶ Allow query without
WHERE
condition.By default delete without condition will raise exception
ConfirmDeleteAllException
. If you want really delete all rows without condition, allow it by calling this method.>>> sqlpuzzle.delete_from('t') Traceback (most recent call last): ... ConfirmDeleteAllException: Are you sure, that you want delete all records? >>> sqlpuzzle.delete_from('t').allow_delete_all() <Delete: DELETE FROM "t">
-
forbid_delete_all
()[source]¶ Forbid query without WHERE condition.
By default delete without condition will raise exception
ConfirmDeleteAllException
. It can be allowed by calling methodallow_delete_all()
. If you want to again forbid it, call this method.
-
Exceptions¶
-
exception
sqlpuzzle.exceptions.
ConfirmDeleteAllException
[source]¶ Raises when you want render delete SQL without any where condition. It is security before droping all data by mistake.
-
exception
sqlpuzzle.exceptions.
ConfirmException
[source]¶ Base confirm exception. If you want to handle any confirm exception (of update or delete) in same way, catch this one.
-
exception
sqlpuzzle.exceptions.
ConfirmUpdateAllException
[source]¶ Raises when you want render update SQL without any where condition. It is security before changing all data by mistake.
-
exception
sqlpuzzle.exceptions.
InvalidArgumentException
(message='')[source]¶ Raises when you pass invalid argument into SQL puzzle. For example instead of column reference some number and so.
>>> sqlpuzzle.select(True) Traceback (most recent call last): ... InvalidArgumentException: Invalid argument: column_name cannot be of type <type 'bool'>.
-
exception
sqlpuzzle.exceptions.
InvalidQueryException
(message='')[source]¶ Specific type of
InvalidArgumentException
. Raises when you passed good arguments but final query does not make sense.>>> sqlpuzzle.select_from('t').on('t2') Traceback (most recent call last): ... InvalidQueryException: Invalid query: You can not set join condition to nothing. Specify join table first.