Initialization support
[Estron backend plugins]


Detailed Description

This module allows DWI to access a variety of data sources using a uniform programming interface: essentially, this is a database API wrapper. This wrapper is very DWI-specific, and is not (really) meant for use by other applications (although it has been). The API borrows conceptual elements from the Postgres libpg API and the ODBC API, and so should be "inutitively obvious" to experienced database programmers. This wrapper allows a variety of different database-access drivers to be operated behind it.

The idea of having a 'wrapper' for database access is not new, and so its worth discussing why 'yet another' wrapper has been created. There are several reasons:

1) This wrapper originially wrapped ODBC. I didn't know ODBC very well when I did this, and I was worried that ODBC sucked. The wrapper allows suckage to be hidden or fixed. 2) The wrapper would allows native Postgress interfaces to be quickly developed, in case the suckage of 1 was too great. 3) The wrapper allows drivers to be added for non-traditional data sources. This would allow DWI to treat these non-traditional data sources in a a database-like way: an important feature, since, to DWI, everything looks like a database. Note: to do this properly, we would need to move the "builder.h" and "builder.c" files from the other directory to here: the builder would be used only by SQL data sources; other data sources would have to handle key-value pairs differently.

This wrapper currently supports only two "providers": ODBC and libdbi (http://libdbi.sourceforge.net).


Typedefs

typedef struct DuiDBConnection_s DuiDBConnection
typedef struct DuiDBRecordSet_s DuiDBRecordSet

Functions

void dui_db_init (void)
DuiDBConnection * dui_connection_new (const char *provider, const char *dbname, const char *username, const char *authentication_token)
void dui_connection_free (DuiDBConnection *conn)
DuiDBRecordSet * dui_connection_exec (DuiDBConnection *, const char *buff)
DuiDBRecordSet * dui_connection_tables (DuiDBConnection *)
DuiDBRecordSet * dui_connection_table_columns (DuiDBConnection *, const char *table_name)
void dui_recordset_free (DuiDBRecordSet *)
int dui_recordset_rewind (DuiDBRecordSet *rs)
int dui_recordset_fetch_row (DuiDBRecordSet *rs)
const char * dui_recordset_get_value (DuiDBRecordSet *, const char *fieldname)
int dui_connection_catch_error (DuiDBConnection *conn, char **ret_str)
int dui_recordset_catch_error (DuiDBRecordSet *, char **ret_str)
struct timespec dui_connection_get_now (DuiDBConnection *conn)
void dui_connection_lock (DuiDBConnection *conn, const char *tablename)
void dui_connection_unlock (DuiDBConnection *conn, const char *tablename)


Function Documentation

int dui_connection_catch_error ( DuiDBConnection *  conn,
char **  ret_str 
)

Return an error code and error string. The design philosphy of the DUI database connection is to be as self-healing as possible, and to report as few errors as possible, so that the system does 'the right thing' as often as possible, so that the API remains easy to use. However, its impossible to ignore all errors; this routine provides a way of getting them.

Returns zero if no error, else returns non-zero. An error string is returned in ret_str if its non-null. The act of calling this routine will also clear the error report (but not the error condition).

Definition at line 173 of file dui-initdb.c.

00174 {
00175     return 0;
00176 }

DuiDBRecordSet* dui_connection_exec ( DuiDBConnection *  ,
const char *  buff 
)

Issue a query on this connection. FYI -- the query is actually performed asynchronously; the record set may not yet contain valid data when this routine returns. Valid data is not available until the (possibly blocking) routine dui_recordset_fetch_row() is called. Note that some queries may result in errors: e.g. if a query uses a table that does not exist. If the resulting recordset contains no rows, you may want to check dui_recordset_catch_error() for errors.

Definition at line 228 of file dui-initdb.c.

00229 {
00230     DuiDBRecordSet *rs = NULL;
00231     DuiDBPlugin *plg;
00232     
00233     if (!conn) return NULL;
00234 
00235     plg = conn->provider;
00236     if (!plg) return NULL;
00237     
00238     if (plg->connection_exec)
00239     {
00240         rs = (plg->connection_exec) (conn, buff);
00241     }
00242     if (!rs) return NULL;
00243     rs->provider = plg;
00244 
00245     return rs;
00246 }

struct timespec dui_connection_get_now ( DuiDBConnection *  conn  )  [read]

Return the the current time, in UTC, at the database server. This value is typically used to provide timestamps for data records. This function is provided as a callable subroutine to ensure portability and common operation for different databases. The SQL statement 'SELECT now() as x' is usally enough for most, but possibly not all databases.

Bug:
timespec needs to be removed.

Definition at line 181 of file dui-initdb.c.

00182 {
00183     DuiDBPlugin *plg;
00184     struct timespec ts = {0,-1};
00185     if (!conn) return ts;
00186 
00187     plg = conn->provider;
00188     if (!plg) return ts;
00189     if (!plg->get_now) return ts;
00190 
00191     ts = (plg->get_now) (conn);
00192     return ts;
00193 }

void dui_connection_lock ( DuiDBConnection *  conn,
const char *  tablename 
)

Lock the indicated tablename in the database server, thus serializing update access. This function is provided as a callable subroutine to ensure portability and common operation for different databases. Not all databases support the same locking mechanisms or locking primitives; this subroutine provides the common api to sereialize database updates.

The subroutine takes a tablename to be locked as the argument. The lock is not expected to fail; if the lock can't be gotten immediately, the subroutine will stall until the lock is available. The unlock is expected to globally commit the changes, making them visible to other clients.

Definition at line 198 of file dui-initdb.c.

00199 {
00200     DuiDBPlugin *plg;
00201 
00202     if (!conn) return;
00203     plg = conn->provider;
00204     if (!plg) return;
00205     if (!plg->lock) return;
00206 
00207     (plg->lock) (conn, tablename);
00208 }

DuiDBConnection* dui_connection_new ( const char *  provider,
const char *  dbname,
const char *  username,
const char *  authentication_token 
)

The dui_connection_new() routine establishes a connection to the indicated database, using the indicated login. The "provider" field is the name of the driver to use. Currently, only "odbc" and "libdbi" are supported.

The ODBC driver expects "dbname" to specify an existing database, and "username" to specify a valid username for logging into the database. The "authentication token" must be a valid password or other ticket that authorizes access.

Definition at line 106 of file dui-initdb.c.

00110 {
00111     DuiDBPlugin *plg = NULL;
00112     DuiDBConnection *dbc = NULL;
00113 
00114     if (!provider) return NULL;
00115 
00116    plg = find_provider (db_provider_list, provider);
00117     if (!plg) 
00118     {
00119         if (!strcmp (provider, "odbc"))
00120         {
00121             load_driver ("libdwi-db-odbc.so", "dui_odbc_init", "ODBC");
00122         }
00123         else
00124         if (!strcmp (provider, "libpg"))
00125         {
00126             load_driver ("libdwi-db-libpg.so", "dui_libpg_init", "Postgres");
00127         }
00128         else
00129         if (!strcmp (provider, "libdbi"))
00130         {
00131             load_driver ("libdwi-db-libdbi.so", "dui_libdbi_init", "DBI");
00132         }
00133 
00134     plg = find_provider (db_provider_list, provider);
00135     }
00136     if (!plg) 
00137     {
00138         PERR ("Can't find database provider \"%s\" for database \"%s\"", 
00139                provider, dbname);
00140         return NULL;
00141     }
00142 
00143     if (!plg->connection_new) return NULL;
00144 
00145     dbc = (plg->connection_new) (dbname, username, authentication_token);
00146     
00147     if (!dbc) return NULL;
00148     dbc->provider = plg;
00149     return dbc;
00150 }

DuiDBRecordSet* dui_connection_table_columns ( DuiDBConnection *  ,
const char *  table_name 
)

Get a list of columns in the named table

Definition at line 274 of file dui-initdb.c.

00275 {
00276     DuiDBRecordSet *rs = NULL;
00277     DuiDBPlugin *plg;
00278     
00279     if (!conn) return NULL;
00280 
00281     plg = conn->provider;
00282     if (!plg) return NULL;
00283     
00284     if (plg->connection_table_columns)
00285     {
00286         rs = (plg->connection_table_columns) (conn, tablename);
00287     }
00288     if (!rs) return NULL;
00289     rs->provider = plg;
00290 
00291     return rs;
00292 }

DuiDBRecordSet* dui_connection_tables ( DuiDBConnection *   ) 

Return a list of tables on this connection.

Definition at line 251 of file dui-initdb.c.

00252 {
00253     DuiDBRecordSet *rs = NULL;
00254     DuiDBPlugin *plg;
00255     
00256     if (!conn) return NULL;
00257 
00258     plg = conn->provider;
00259     if (!plg) return NULL;
00260     
00261     if (plg->connection_tables)
00262     {
00263         rs = (plg->connection_tables) (conn);
00264     }
00265     if (!rs) return NULL;
00266     rs->provider = plg;
00267 
00268     return rs;
00269 }

void dui_connection_unlock ( DuiDBConnection *  conn,
const char *  tablename 
)

Bug:
under what cases would we need to support rollback?

Definition at line 213 of file dui-initdb.c.

00214 {
00215     DuiDBPlugin *plg;
00216     if (!conn) return;
00217 
00218     plg = conn->provider;
00219     if (!plg) return;
00220     if (!plg->unlock) return;
00221 
00222     (plg->unlock) (conn, tablename);
00223 }

void dui_db_init ( void   ) 

Must call this before using this subsystem

Definition at line 84 of file dui-initdb.c.

00085 {
00086 }

int dui_recordset_fetch_row ( DuiDBRecordSet *  rs  ) 

Prep a row. Basically, this gets the 'next' row out of the database. Subsequent field fetches are for this row. Returns zero if there are no more rows, else returns a non-zero value if there are more rows.

Definition at line 334 of file dui-initdb.c.

00335 {
00336     DuiDBPlugin *plg;
00337     
00338     if (!rs) return 0;
00339 
00340     plg = rs->provider;
00341     if (!plg) return 0;
00342     
00343     if (plg->recordset_fetch_row)
00344     {
00345         return (plg->recordset_fetch_row) (rs);
00346     }
00347     return 0;
00348 }

void dui_recordset_free ( DuiDBRecordSet *   ) 

Release the record set when one is done with it

Definition at line 297 of file dui-initdb.c.

00298 {
00299     DuiDBPlugin *plg;
00300     
00301     if (!rs) return;
00302 
00303     plg = rs->provider;
00304     if (!plg) return;
00305     
00306     if (plg->recordset_free)
00307     {
00308         (plg->recordset_free) (rs);
00309     }
00310 }

const char* dui_recordset_get_value ( DuiDBRecordSet *  ,
const char *  fieldname 
)

Get the field value by name. This is a little different/easier than the usual trick of getting it by column number.

Definition at line 353 of file dui-initdb.c.

00354 {
00355     DuiDBPlugin *plg;
00356     
00357     if (!rs) return NULL;
00358 
00359     plg = rs->provider;
00360     if (!plg) return NULL;
00361     
00362     if (plg->recordset_get_value)
00363     {
00364         return (plg->recordset_get_value) (rs, fieldname);
00365     }
00366     return NULL;
00367 }

int dui_recordset_rewind ( DuiDBRecordSet *  rs  ) 

Set the row pointer to the start of the the recordset. Returns 0 if there is no first row.

Definition at line 315 of file dui-initdb.c.

00316 {
00317     DuiDBPlugin *plg;
00318     
00319     if (!rs) return 0;
00320 
00321     plg = rs->provider;
00322     if (!plg) return 0;
00323     
00324     if (plg->recordset_rewind)
00325     {
00326         return (plg->recordset_rewind) (rs);
00327     }
00328     return 0;
00329 }


Generated on Tue Apr 29 21:27:53 2008 for estron by  doxygen 1.5.5