Developer guide

This guide details how to create plugins for use db-patch with other databases, drivers or for create customized patches.

Adding ODBC connections

Currently only three databases are supported: MySQL, PostgreSQL and SQLite. However, the mechanism for support other databases is simple.

For connect to one database using ODBC only it is necessary define correclty the connection string. However, each database use its keywords for this purpose. Therefore, it is necessary associate each custom keyword with the keyword used by db-patch. The next table shows the default keywords used by db-patch for create an ODBC connection string.

Keyword Meaning
USER Database user
PASSWORD Database password
SERVER Hostname of database server
PORT Port of database server
DRIVER ODBC driver
CHARSET Database charset

For instance, PostgreSQL uses the keyword UID instance of USER and PWD instance of PASSWORD. Therefore, it is necessary customize the connection string. To do this, it is necessary create a customized OdbcQueryBuilder and overwrite the method get_customized_keywords as it is shown in the next code listing.

import dbpatch.connection.odbc as odbc
from dbpatch.loader import Registry

class PostgreSQLQueryBuilder(odbc.OdbcQueryBuilder):

   NAME = 'postgresql'

   def get_internal_database(self):
       return 'postgres'

   def get_all_databases_query(self):
       return "SELECT datname FROM pg_database WHERE datistemplate = false"

   def get_customized_keywords(self):
       return {'USER'     : 'UID',
               'PASSWORD' : 'PWD'}


def register(module_id):
   Registry.register(module_id, PostgreSQLQueryBuilder)

The previous code listing shows other two methods that should be overwritten:

  • get_internal_database. Return the name of the internal database used for the database engine. db-patch will connect with this database for recover the full list of working databases.
  • get_all_databases_query. Return the query that will recover the full list of working databases.

Other two aspects should be noted:

  • The NAME class attribute. Define the name that it will be used by db-patch for register the customized ODBC QueryBuilder.

    Note

    It is mandatory define the NAME attribute. The NAME is provided by the -E (–db-engine) command line option.

  • The register module method. Register the customized OdbcQueryBuilder for to be used by db-patch

    Note

    If the customized OdbcQueryBuilder is not registered, db-patch will not found it.

The method that creates the final ODBC connection string is OdbcQueryBuilder.get_connection_string. It is possible overwrite, but previously it is recommended to show the code of this method because it makes checks, and add optional options.

Adding native connections

It is possible connect with the database engine using specific drivers instead of ODBC. For to do this, it is necessary provide a customized patcher.connection.Connection class and to use the –connection-plugins command line option.

For drivers compliant with the DB-API 2.0 specification the class patcher.connection.DbApi2Connection is provided. A new driver that use this class as parent class only should overwrite a few methods, define the NAME class attribute and register the connection (create a module method called register and use the method dbpatch.connection.ConnectionFactory.register_connection). Next, the methods to overwrite are enumerated.

  • connect. Connect with one database.
  • get_internal_database. Return the name of the internal database.
  • get_all_databases. Recover the full list of databases.

Currently there are three native implementations that can be used as examples:

Note

For to use your new native connection it is necessary to provide the next command line options to db-patch

  • -N or –native
  • –connection-plugins

Creating new patches

For create a new patch only it is necessary inherit of the class dbpatch.patch.Patch, provide an implementation of the execute method, add the EXTENSION class attribute, register the new patch (creating a module method called register and using the method dbpatch.patch.PatchFactory.register), and use the –patch-plugins command line option.

As example see the implementation of raw and sql patches (the code shown below correspond to used for manage raw patches).

import dbpatch.options
from dbpatch.log import LogFactory
import dbpatch.patch
from dbpatch.loader import Registry


class RawPatch(dbpatch.patch.Patch):
   '''
   Execute all the content of a file in a single query. Useful by
   example for PL SQL scripts. Be careful, you must introduce
   a single query.

   The keyword 'mydb' will be replaced by each database name
   '''

   REGISTRY_ID = 'raw'

   def __init__(self):
       dbpatch.patch.Patch.__init__(self)
       self._log  = LogFactory().get_logger(RawPatch.__name__)
       patch_file = self._options.get_option(dbpatch.options.PATCH_FILE)
       self._queries = open(patch_file, 'r').read()


   def execute(self, db_name):
       connection = self.connect_to(db_name)
       queries = self._queries.replace('mydb', db_name)
       statement = self.create_statement(queries)
       status = statement.execute()
       if not status:
           return False

       return True


def register(module_id):
   Registry.register(RawPatch)

Providing more options

Your new plugins could require more options. For this purpose you can use the –extra-opts command line option. This option recover a properties file and add them into the dbpatch.options.Options object. That is, for the next file

[myopt]
opt1 = first
opt2 = second

using the command line option

$> db-patch [...] --extra-opts myopt.cfg

your plugins can recover this properties from the Options object using the keywords myopt.opt1 and myopt.opt2 (section.option_name)

[...]

your_opt1 = Context().options.get_option('myopt.opt1')
your_opt2 = Context().options.get_option('myopt.opt2')

[...]

Table Of Contents

Previous topic

User guide

Next topic

db-patch

This Page