00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00030 #include "config.h"
00031 #include "perr.h"
00032
00033 #ifdef USE_LIBDBI
00034
00035 #include <string.h>
00036 #include <dbi/dbi.h>
00037 #include "util.h"
00038 #include "dui-libdbi.h"
00039 #include "dui-initdb-p.h"
00040
00041
00042
00043
00044 typedef struct DuiLibDBIConnection_s DuiLibDBIConnection;
00045 typedef struct DuiLibDBIRecordSet_s DuiLibDBIRecordSet;
00046
00047 struct DuiLibDBIConnection_s
00048 {
00049 DuiDBConnection dbcon;
00050 char * dbname;
00051 char * username;
00052 dbi_driver driver;
00053 dbi_conn conn;
00054
00055 GList * free_pool;
00056 };
00057
00058 struct DuiLibDBIRecordSet_s
00059 {
00060 DuiDBRecordSet recset;
00061 DuiLibDBIConnection *conn;
00062 dbi_result result;
00063 long long nrows;
00064 };
00065
00066
00067
00068 DuiDBConnection *
00069 dui_libdbi_connection_new (const char * dbname,
00070 const char * username,
00071 const char * authentication_token)
00072 {
00073 int rc;
00074 dbi_driver driver;
00075 dbi_conn conn;
00076 const char * errmsg;
00077 DuiLibDBIConnection *dui_conn;
00078
00079
00080 rc = dbi_initialize (NULL);
00081 if (0 >= rc)
00082 {
00083 PERR ("Can't find any libdbi drivers, rc=%d\n", rc);
00084 return NULL;
00085 }
00086
00089 driver = dbi_driver_list (NULL);
00090 driver = dbi_driver_open ("pgsql");
00091 PINFO ("Using libdbi driver \"%s\"\n", dbi_driver_get_name(driver));
00092 if (!driver)
00093 {
00094 PERR ("Couldn't load libdbi database driver\n");
00095 goto shutdown;
00096 }
00097
00098 conn = dbi_conn_open (driver);
00099 conn = dbi_conn_new ("pgsql");
00100 if (!conn)
00101 {
00102 PERR ("Couldn't connect to database with libdbi\n");
00103 goto shutdown;
00104 }
00105
00106
00107 rc = dbi_conn_set_option(conn, "username", username);
00108
00109 rc = dbi_conn_set_option(conn, "dbname", dbname);
00110
00111 rc = dbi_conn_connect (conn);
00112 if (rc)
00113 {
00114 dbi_conn_error (conn, &errmsg);
00115 PERR("Couldn't log into database \"%s\" with username \"%s\":\n"
00116 "\terrmsg: %s\n",
00117 dbname, username, errmsg);
00118 goto disconnect;
00119 }
00120
00121 dui_conn = g_new0 (DuiLibDBIConnection, 1);
00122 dui_conn->driver = driver;
00123 dui_conn->conn = conn;
00124 dui_conn->free_pool = NULL;
00125
00126 dui_conn->dbname = g_strdup (dbname);
00127 dui_conn->username = g_strdup (username);
00128
00129 return &dui_conn->dbcon;
00130
00131 disconnect:
00132 dbi_conn_close (conn);
00133 shutdown:
00134 dbi_shutdown();
00135 return NULL;
00136 }
00137
00138
00139 static void dui_libdbi_recordset_free (DuiLibDBIRecordSet *rs);
00140
00141 void
00142 dui_libdbi_connection_free (DuiDBConnection *dbc)
00143 {
00144 GList *node;
00145 DuiLibDBIConnection *conn = (DuiLibDBIConnection *)dbc;
00146 if (!conn) return;
00147
00148 for (node=conn->free_pool; node; node=node->next)
00149 {
00150 dui_libdbi_recordset_free (node->data);
00151 }
00152 g_list_free (conn->free_pool);
00153 conn->free_pool = NULL;
00154
00155 g_free (conn->dbname);
00156 g_free (conn->username);
00157 dbi_conn_close (conn->conn);
00158 dbi_shutdown();
00159 }
00160
00161
00162
00163 DuiDBRecordSet *
00164 dui_libdbi_connection_exec (DuiDBConnection *dbc, const char * buff)
00165 {
00166 DuiLibDBIConnection *conn = (DuiLibDBIConnection *) dbc;
00167 DuiLibDBIRecordSet *rs;
00168 dbi_result result;
00169
00170 if (!conn) return NULL;
00171
00172 PINFO ("query=%s", buff);
00173 result = dbi_conn_query(conn->conn, buff);
00174 if (!result)
00175 {
00176 dbi_error_flag flg = dbi_conn_error_flag(conn->conn);
00177 if (DBI_ERROR_NONE != flg)
00178 {
00179 char * ret_str = NULL;
00180 dbi_conn_error (conn->conn, (const char **) &ret_str);
00181 PERR ("Database query execution error:\n%s\n", ret_str);
00182 }
00183 return NULL;
00184 }
00185
00186 if (conn->free_pool)
00187 {
00188 rs = conn->free_pool->data;
00189 conn->free_pool = g_list_remove (conn->free_pool, rs);
00190 }
00191 else
00192 {
00193 rs = g_new (DuiLibDBIRecordSet, 1);
00194 rs->conn = conn;
00195 }
00196
00197 rs->nrows = -1;
00198 rs->result = result;
00199 return &rs->recset;
00200 }
00201
00202
00203
00204 void
00205 dui_libdbi_recordset_release (DuiDBRecordSet *recset)
00206 {
00207 DuiLibDBIRecordSet *rs = (DuiLibDBIRecordSet *) recset;
00208 if (!rs) return;
00209
00210 dbi_result_free(rs->result);
00211 rs->conn->free_pool = g_list_prepend (rs->conn->free_pool, rs);
00212 }
00213
00214
00215
00216 static void
00217 dui_libdbi_recordset_free (DuiLibDBIRecordSet *rs)
00218 {
00219 if (!rs) return;
00220 g_free (rs);
00221 }
00222
00223
00224
00225 static gint
00226 dui_libdbi_recordset_rewind (DuiDBRecordSet *recset)
00227 {
00228 DuiLibDBIRecordSet *rs = (DuiLibDBIRecordSet *) recset;
00229 int rc;
00230 if (!rs) return 0;
00231 rc = dbi_result_first_row (rs->result);
00232 return rc;
00233 }
00234
00235
00236
00237 int
00238 dui_libdbi_recordset_fetch_row (DuiDBRecordSet *recset)
00239 {
00240 DuiLibDBIRecordSet *rs = (DuiLibDBIRecordSet *) recset;
00241 int rc;
00242 if (!rs) return 0;
00243 rc = dbi_result_next_row (rs->result);
00244 return rc;
00245 }
00246
00247
00248
00249 const gchar *
00250 dui_libdbi_recordset_get_value (DuiDBRecordSet *recset, const char * fieldname)
00251 {
00252 DuiLibDBIRecordSet *rs = (DuiLibDBIRecordSet *) recset;
00253 const gchar *val;
00254 const gchar *fn;
00255 gushort field_type;
00256
00257 if (!rs) return NULL;
00258
00259
00260
00261 fn = strrchr (fieldname, '.');
00262 if (fn) fn++;
00263 if (!fn) fn = fieldname;
00264 if (!fn) return NULL;
00265 if ('\0' == fn[0]) return NULL;
00266 if (0 > rs->nrows)
00267 {
00268 rs->nrows = dbi_result_get_numrows (rs->result);
00269 }
00270 if (0 >= rs->nrows) return NULL;
00271
00272 field_type = dbi_result_get_field_type(rs->result, fn);
00273 switch (field_type)
00274 {
00275 case DBI_TYPE_STRING:
00276 val = dbi_result_get_string(rs->result, fn);
00277 return val;
00278
00279 case DBI_TYPE_INTEGER:
00280 {
00281 static char buff[40];
00282
00283
00284 long lll = dbi_result_get_long(rs->result, fn);
00285 sprintf (buff, "%ld", lll);
00286 return buff;
00287 }
00288 case DBI_TYPE_DECIMAL:
00289 {
00290 static char flbuff[40];
00291 int fsz = dbi_result_get_field_size (rs->result, fn);
00292 double ddd = 0.0;
00293 switch (fsz & ~DBI_DECIMAL_UNSIGNED)
00294 {
00295 case 0:
00296 case DBI_DECIMAL_SIZE4:
00297 ddd = dbi_result_get_float(rs->result, fn);
00298 break;
00299 case DBI_DECIMAL_SIZE8:
00300 ddd = dbi_result_get_double(rs->result, fn);
00301 break;
00302 default:
00303 PERR ("libdbi database driver:\n"
00304 "unhandled float size %x for field=%s", fsz, fieldname);
00305 }
00306 sprintf (flbuff, "%25.18g", ddd);
00307 return flbuff;
00308 }
00309 case DBI_TYPE_DATETIME:
00310 {
00311 time_t secs = dbi_result_get_datetime (rs->result, fn);
00312 static char datebuff[140];
00313 xxxgnc_secs_to_iso8601_buff (secs, datebuff);
00314 return datebuff;
00315 }
00316 case 0:
00317 PERR("DUI libdbi field \"%s\" is not in the SQL Query\n",
00318 fieldname);
00319 return NULL;
00320
00321 default:
00322 PERR("DUI libdbi field \"%s\" has unsupported field type %d\n",
00323 fieldname, field_type);
00324 return NULL;
00325 }
00326
00327 return val;
00328 }
00329
00330
00331
00332 static gint
00333 dui_libdbi_recordset_get_error (DuiDBRecordSet *recset, char **ret_str)
00334 {
00335 dbi_error_flag rc;
00336 DuiLibDBIRecordSet *rs = (DuiLibDBIRecordSet *) recset;
00337 if (!rs)
00338 {
00340 if (ret_str) *ret_str = "Called with null recordset";
00341 return -1;
00342 }
00343 rc = dbi_conn_error_flag (rs->conn->conn);
00344 dbi_conn_error (rs->conn->conn, (const char **) ret_str);
00345 return (int) rc;
00346 }
00347
00348
00349
00350 static void
00351 dui_libdbi_plugin_free (DuiDBPlugin *plg)
00352 {
00353 g_free (plg);
00354 }
00355
00356
00357
00358 static DuiDBPlugin *
00359 dui_libdbi_plugin_new (void)
00360 {
00361 DuiDBPlugin *plg;
00362 plg = g_new0 (DuiDBPlugin, 1);
00363 plg->db_provider_name = "libdbi";
00364 plg->plugin_free = dui_libdbi_plugin_free;
00365 plg->connection_new = dui_libdbi_connection_new;
00366 plg->connection_free = dui_libdbi_connection_free;
00367 plg->connection_exec = dui_libdbi_connection_exec;
00368 plg->connection_tables = NULL;
00369 plg->connection_table_columns = NULL;
00370 plg->recordset_free = dui_libdbi_recordset_release;
00371 plg->recordset_rewind = dui_libdbi_recordset_rewind;
00372 plg->recordset_fetch_row = dui_libdbi_recordset_fetch_row;
00373 plg->recordset_get_value = dui_libdbi_recordset_get_value;
00374 plg->recordset_get_error = dui_libdbi_recordset_get_error;
00375
00376 return plg;
00377 }
00378
00379 #endif
00380
00381
00382 void
00383 dui_libdbi_init (void)
00384 {
00385 #ifdef USE_LIBDBI
00386 DuiDBPlugin *plg;
00387 plg = dui_libdbi_plugin_new();
00388 dui_db_provider_register (plg);
00389 #else
00390
00391 PERR ("The DWI db drivers were compiled without libdbi support");
00392 #endif
00393 }
00394
00395