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) |
| 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.
| 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.
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 | |||
| ) |
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 | ) |
| 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 }
1.5.5