Database Abstraction Layer (DBAL) for Python 2.6+
Project description
Database Abstraction Layer (DBAL) for Python 2.6+.
pyDBAL library is the improved and optimised port of Doctrine DBAL project.
Installation
$ pip install pydbal
Requirements
For using mysql driver MySQLdb library is required. Optionally lrucache is required to maintain memory safe cache operations.
Basic Usage
To open new connection import Connection from pydbal.connection package and initialise Connection class for a required driver with desired parameters.
from pydbal.connection import Connection
conn = Connection('mysql', host='localhost', user='root', database='mydb')
pyDBAL currently supports the following drivers: mysql and sqlite. You can create a custom driver by inheriting pydbal.drivers.BaseDriver and passing to Connection constructor.
Query Statements
To SELECT data from the database you may use query method. This method will return the instance of pydbal.statement.Statement.
# simple fetch generator
for row in conn.query('SELECT * FROM table'):
print(row)
# same as the above but fetch mode can be applied (Connection.FETCH_*)
for row in conn.query('SELECT * FROM table').iterate(fetch_mode=Connection.FETCH_OBJECT):
print(row)
# fetch row by row
result = conn.query('SELECT * FROM table')
row1 = result.fetch()
row2 = result.fetch()
# fetch all rows
rows = conn.query('SELECT * FROM table').fetch_all()
# fetch single value from column
count = conn.query('SELECT COUNT(*) FROM table').fetch_column()
# fetch all values from column by index
ids = conn.query('SELECT id FROM table').fetch_all(fetch_mode=Connection.FETCH_COLUMN, column_index=0)
Execute Statements
To execute INSERT, UPDATE or DELETE statements you may use execute method. This method will return number of affected rows.
# INSERT
conn.execute('INSERT INTO table VALUES (?)', [val1, val2, val3])
last_insert_id = conn.last_insert_id()
# UPDATE
affected_rows = conn.execute('UPDATE table SET column = ? WHERE id = ?', val1, id_)
# DELETE
affected_rows = conn.execute('DELETE FROM table WHERE id = ?', id_)
Statement Parameters
Both query and execute methods support safe parameter binding by passing arguments after the first sql argument.
# single positional parameter
row = conn.query('SELECT * FROM table WHERE id = ?', id_).fetch()
# multiple positional parameters
row = conn.query('SELECT * FROM table WHERE id = ? OR id = ?', id1, id2).fetch()
# named parameters
row = conn.query('SELECT * FROM table WHERE id = :id1 OR id = :id2', id1=id1, id2=id2).fetch()
# iterable parameters
row = conn.query('SELECT * FROM table WHERE id IN (?)', [id1, id2]).fetch()
Transactions
pyDBAL supports transactional operations.
conn.begin_transaction()
try:
# ... execute statements ...
conn.commit()
return smth
except:
conn.rollback()
raise
# same as the above
def trans(conn):
# ... execute statements ...
return smth
smth = conn.transaction(trans)
If database platform supports savepoints you may enable and use nested transactions.
conn.set_nest_transactions_with_savepoints(True)
conn.begin_transaction()
# ... execute statements 1 ...
conn.begin_transaction()
# ... execute statements 2 ...
conn.commit() # commit 1
conn.rollback() # rollback 2
# to control savepoints manually
conn.create_savepoint('MYSAVEPOINT')
conn.release_savepoint('MYSAVEPOINT')
conn.rollback_savepoint('MYSAVEPOINT')
SQL Builder
To make writing SQL statements more simple and flexible it’s suggested to use pydbal.builder.SQLBuilder.
# SELECT
sqb = (
conn.sql_builder()
.select('t1.id', 't2.id', 'SUM(t1.col) AS special')
.from_('table1', 't1')
.join('t1', 'table2', 't2', 't2.id = t1.id')
.where('t1.col = :val')
.set_parameter('val', val)
.group_by('t1.col')
.having('special IS NOT NULL')
.order_by('t2.id')
)
for row in sqb.execute():
print(row)
# INSERT
last_insert_id = (
conn.sql_builder()
.insert('table')
.values({'col1': val1, 'col2': val2})
).execute()
# UPDATE
affected_rows = (
conn.sql_builder()
.update('table')
.set('col1', val1)
.set('col2', val2)
.where('id = :id')
.set_parameter('id', id_)
).execute()
# DELETE
affected_rows = (
conn.sql_builder()
.delete('table')
.where('id = ?')
.set_parameter(0, id_)
).execute()
Expression Builder
WHERE, HAVING and JOIN ... ON expressions can be created using pydbal.builder.ExpressionBuilder.
expr = conn.get_expression_builder()
# or via SQL Builder instance
# expr = sqb.expr()
sqb.where(
expr.and_x(expr.eq('a', 'b'), expr.is_null('c'))
.or_x(
expr.and_x('d IS NULL', expr.in_('e', ['1', '2', '3'])),
expr.neq('f', expr.literal('abc'))
)
)
Schema Manager
pyDBAL comes with simple read only SQL schema manager. It supports listing of databases, tables, views, columns, indexes and foreign keys. Internal database queries are cached with pydbal.cache mechanisms.
sm = conn.get_schema_manager()
# database names
db_names = sm.get_database_names()
# views
views = sm.get_views()
view_names = sm.get_view_names()
# tables
tables = sm.get_tables()
table_names = sm.get_table_names()
# columns
table_columns = sm.get_table_columns('table')
table_column_names = sm.get_table_column_names('table')
# indexes
table_indexes = sm.get_table_indexes('table')
table_index_names = sm.get_table_index_names('table')
# foreign keys
table_foreign_keys = sm.get_table_foreign_keys('table')
table_foreign_key_names = sm.get_table_foreign_key_names('table')
Thread-safe Connection
pyDBAL v0.10+ supports thread-safe connection functionality implemented in pydbal.threading module.
from pydbal.threading import SafeConnection
conn = SafeConnection('mysql', host='localhost', user='root', database='mydb')
SafeConnection wrapper class maintains active connections in locked pool and provides helper methods for manipulating your data. Class implements method locked() which should be passed to with statement. It generates isolated connection context, that can be used for sending non-trivial commands to the original pydbal.connection.Connection object.
# simple fetch generator
for row in conn.query('SELECT * FROM table'):
print(row)
# fetch one row
row = conn.fetch('SELECT * FROM table WHERE id = ?', id_)
# fetch all rows
rows = conn.fetch_all('SELECT * FROM table')
# fetch single value from column
count = conn.fetch_column('SELECT COUNT(*) FROM table')
# UPDATE or DELETE queries
affected_rows = conn.execute('UPDATE table SET column = ? WHERE id = ?', val1, id_)
# INSERT query with last inserted ID
with conn.locked() as _conn:
_conn.execute('INSERT INTO table VALUES (?)', [val1, val2, val3])
last_insert_id = _conn.last_insert_id()
# transaction callback
def trans(_conn):
# ... execute statements ...
return smth
smth = conn.transaction(trans)
License
Library is available under the MIT license. The included LICENSE file describes this in detail.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file pydbal-0.12.tar.gz
.
File metadata
- Download URL: pydbal-0.12.tar.gz
- Upload date:
- Size: 28.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1e89e9e87dc170f6fd487cbc93d9d5e8c86b810efdd5981a905c065ddf00c54c |
|
MD5 | 3e546be78cfa02d04787d295d52af416 |
|
BLAKE2b-256 | 45626b00e5f477690e260853e6f7ef71987791668ca58501314fb0162d2754d8 |