Package: pydbal
Database Abstraction Layer (DBAL) for Python 2.6+.pyDBAL library is the improved and optimised port ofDoctrine
DBALproject.Installation$pipinstallpydbalRequirementsFor usingmysqldriverMySQLdblibrary is required. Optionallylrucacheis required to maintain memory safe cache operations.Basic UsageTo open new connection importConnectionfrompydbal.connectionpackage and initialiseConnectionclass for a required driver with
desired parameters.frompydbal.connectionimportConnectionconn=Connection('mysql',host='localhost',user='root',database='mydb')pyDBAL currently supports the following drivers:mysqlandsqlite. You can create a custom driver by inheritingpydbal.drivers.BaseDriverand passing toConnectionconstructor.Query StatementsToSELECTdata from the database you may usequerymethod. This
method will return the instance ofpydbal.statement.Statement.# simple fetch generatorforrowinconn.query('SELECT * FROM table'):print(row)# same as the above but fetch mode can be applied (Connection.FETCH_*)forrowinconn.query('SELECT * FROM table').iterate(fetch_mode=Connection.FETCH_OBJECT):print(row)# fetch row by rowresult=conn.query('SELECT * FROM table')row1=result.fetch()row2=result.fetch()# fetch all rowsrows=conn.query('SELECT * FROM table').fetch_all()# fetch single value from columncount=conn.query('SELECT COUNT(*) FROM table').fetch_column()# fetch all values from column by indexids=conn.query('SELECT id FROM table').fetch_all(fetch_mode=Connection.FETCH_COLUMN,column_index=0)Execute StatementsTo executeINSERT,UPDATEorDELETEstatements you may useexecutemethod. This method will return number of affected rows.# INSERTconn.execute('INSERT INTO table VALUES (?)',[val1,val2,val3])last_insert_id=conn.last_insert_id()# UPDATEaffected_rows=conn.execute('UPDATE table SET column = ? WHERE id = ?',val1,id_)# DELETEaffected_rows=conn.execute('DELETE FROM table WHERE id = ?',id_)Statement ParametersBothqueryandexecutemethods support safe parameter binding by
passing arguments after the firstsqlargument.# single positional parameterrow=conn.query('SELECT * FROM table WHERE id = ?',id_).fetch()# multiple positional parametersrow=conn.query('SELECT * FROM table WHERE id = ? OR id = ?',id1,id2).fetch()# named parametersrow=conn.query('SELECT * FROM table WHERE id = :id1 OR id = :id2',id1=id1,id2=id2).fetch()# iterable parametersrow=conn.query('SELECT * FROM table WHERE id IN (?)',[id1,id2]).fetch()TransactionspyDBAL supports transactional operations.conn.begin_transaction()try:# ... execute statements ...conn.commit()returnsmthexcept:conn.rollback()raise# same as the abovedeftrans(conn):# ... execute statements ...returnsmthsmth=conn.transaction(trans)If database platform supportssavepointsyou 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 1conn.rollback()# rollback 2# to control savepoints manuallyconn.create_savepoint('MYSAVEPOINT')conn.release_savepoint('MYSAVEPOINT')conn.rollback_savepoint('MYSAVEPOINT')SQL BuilderTo make writing SQL statements more simple and flexible it’s suggested
to usepydbal.builder.SQLBuilder.# SELECTsqb=(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'))forrowinsqb.execute():print(row)# INSERTlast_insert_id=(conn.sql_builder().insert('table').values({'col1':val1,'col2':val2})).execute()# UPDATEaffected_rows=(conn.sql_builder().update('table').set('col1',val1).set('col2',val2).where('id = :id').set_parameter('id',id_)).execute()# DELETEaffected_rows=(conn.sql_builder().delete('table').where('id = ?').set_parameter(0,id_)).execute()Expression BuilderWHERE,HAVINGandJOIN ... ONexpressions can be created
usingpydbal.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 ManagerpyDBAL 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 withpydbal.cachemechanisms.sm=conn.get_schema_manager()# database namesdb_names=sm.get_database_names()# viewsviews=sm.get_views()view_names=sm.get_view_names()# tablestables=sm.get_tables()table_names=sm.get_table_names()# columnstable_columns=sm.get_table_columns('table')table_column_names=sm.get_table_column_names('table')# indexestable_indexes=sm.get_table_indexes('table')table_index_names=sm.get_table_index_names('table')# foreign keystable_foreign_keys=sm.get_table_foreign_keys('table')table_foreign_key_names=sm.get_table_foreign_key_names('table')Thread-safe ConnectionpyDBAL v0.10+ supports thread-safe connection functionality implemented inpydbal.threadingmodule.frompydbal.threadingimportSafeConnectionconn=SafeConnection('mysql',host='localhost',user='root',database='mydb')SafeConnectionwrapper class maintains active connections in locked pool
and provides helper methods for manipulating your data. Class implements methodlocked()which should be passed towithstatement. It generates
isolated connection context, that can be used for sending non-trivial commands
to the originalpydbal.connection.Connectionobject.# simple fetch generatorforrowinconn.query('SELECT * FROM table'):print(row)# fetch one rowrow=conn.fetch('SELECT * FROM table WHERE id = ?',id_)# fetch all rowsrows=conn.fetch_all('SELECT * FROM table')# fetch single value from columncount=conn.fetch_column('SELECT COUNT(*) FROM table')# UPDATE or DELETE queriesaffected_rows=conn.execute('UPDATE table SET column = ? WHERE id = ?',val1,id_)# INSERT query with last inserted IDwithconn.locked()as_conn:_conn.execute('INSERT INTO table VALUES (?)',[val1,val2,val3])last_insert_id=_conn.last_insert_id()# transaction callbackdeftrans(_conn):# ... execute statements ...returnsmthsmth=conn.transaction(trans)LicenseLibrary is available under the MIT license. The included LICENSE file
describes this in detail.