https://github.com/lokhman/pydbal
Optimised Database Abstraction Layer (DBAL) for Python 2.6+
https://github.com/lokhman/pydbal
abstraction database library python
Last synced: 6 months ago
JSON representation
Optimised Database Abstraction Layer (DBAL) for Python 2.6+
- Host: GitHub
- URL: https://github.com/lokhman/pydbal
- Owner: lokhman
- License: mit
- Created: 2016-03-24T18:17:10.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2017-02-06T15:06:34.000Z (over 9 years ago)
- Last Synced: 2025-11-27T12:25:45.341Z (7 months ago)
- Topics: abstraction, database, library, python
- Language: Python
- Homepage: https://lokhman.github.io/pydbal/
- Size: 76.2 KB
- Stars: 2
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
pyDBAL
======
Database Abstraction Layer (**DBAL**) for Python 2.6+.
pyDBAL library is the improved and optimised port of [Doctrine
DBAL](http://www.doctrine-project.org/projects/dbal.html) 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.