Due to the problem of maintainence of dbmail with backends, I have begun
working with David Parker (author of libdbi, a portable native database
layer) on creating a backend for dbmail. This would expand dbmail to the
following backends at this time:
mysql
pgsql
msql
firebird
oracle
sqlite
2/3s of the work required is done. Places work needs to be done are marked
by XXX TODO. Patch is attached.
Index: dbmail/libdbi/dblibdbi.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ dbmail/libdbi/dblibdbi.c 2004-08-26 02:17:50.102957232 -0400
@@ -0,0 +1,273 @@
+
+/* Copyright (C) 2004 Dan Weber <[EMAIL PROTECTED]>
+ * Copyright (C) 2004 David Parker <[EMAIL PROTECTED]>
+ * $Id$
+ * /
+
+/*
+ *
+ * libdbi driver file.
+ * functions for connecting and talking to the libdbi layer
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "db.h"
+#include <dbi/dbi.h>
+#include "dbmail.h"
+#include "dbmailtypes.h"
+#include <string.h>
+
+db_param_t dbparams;
+dbi_conn conn;
+dbi_result result;
+dbi_result msgbuf_result;
+dbi_result stored_result;
+
+
+int db_connect() {
+ dbi_initialize(NULL);
+ conn = dbi_conn_new(dbparams.dbtype);
+
+ if (!conn) {
+ trace(TRACE_ERROR,"Connection to Database Failed at
dbi_conn_new");
+ dbi_shutdown();
+ return -1;
+ }
+
+ /* Begin Setting Parameters */
+ if (dbparams.host)
+ dbi_conn_set_option(conn, "host", dbparams.host);
+ if (dbparams.user)
+ dbi_conn_set_option(conn, "username", dbparams.user);
+ if (dbparams.pass)
+ dbi_conn_set_option(conn, "password", dbparams.pass);
+ if (dbparams.db)
+ dbi_conn_set_option(conn, "dbname", dbparams.db);
+ if (dbparams.port)
+ dbi_conn_set_option(conn, "port", dbparams.port);
+ /* End Setting Parameters */
+
+ // Create Connection
+ if ((dbi_conn_connect(conn)) == -1) {
+ trace(TRACE_ERROR, "Connection failed at dbi_conn_connect");
+ dbi_shutdown();
+ return -1;
+ }
+}
+
+unsigned db_num_rows()
+{
+ /* mysql_store_result can return NULL. If this is
+ * true, res will be zero, and naturally num_rows
+ * should return 0 */
+ if (!result)
+ return 0;
+
+ return dbi_result_get_numrows(result);
+}
+
+unsigned db_num_fields()
+{
+ if (!result)
+ return 0;
+
+ return dbi_result_get_numfields(result);
+}
+
+void db_free_result()
+{
+ if (result)
+ dbi_result_free(result);
+ else
+ trace(TRACE_WARNING, "%s,%s: Trying to free result set "
+ "that is already NULL!", __FILE__, __func__);
+ result = NULL;
+}
+
+const char *db_get_result(unsigned row, unsigned field)
+{
+ const char *fieldvalue = NULL;
+
+ if (!result) {
+ trace(TRACE_WARNING, "%s,%s: result set is null\n",
+ __FILE__, __func__);
+ return NULL;
+ }
+
+ if ((row >= db_num_rows()) || (field >= db_num_fields())) {
+ trace(TRACE_WARNING, "%s, %s: "
+ "row = %u, field = %u, bigger than size of result set",
+ __FILE__, __func__, row, field);
+ return NULL;
+ }
+
+ if (dbi_result_seek_row(result, row) < 1) {
+ trace(TRACE_WARNING, "%s,%s: row is NULL\n",
+ __FILE__, __func__);
+ return NULL;
+ }
+
+ result = last_row[field];
+ fieldvalue = dbi_result_get_string_idx(result, field);
+ if (fieldvalue == NULL)
+ trace(TRACE_WARNING, "%s,%s: result is null\n",
+ __FILE__, __func__);
+ return fieldvalue;
+}
+
+int db_disconnect()
+{
+ if (result)
+ db_free_result();
+ dbi_conn_close(conn);
+ // XXX dbi_shutdown() ??
+ return 0;
+}
+
+int db_check_connection()
+{
+ if (dbi_conn_ping(conn) == 0) {
+ trace(TRACE_DEBUG, "%s,%s: no database connection, trying "
+ "to establish on.", __FILE__, __func__);
+ if (db_connect() < 0) {
+ trace(TRACE_ERROR, "%s,%s: unable to connect to "
+ "database.", __FILE__, __func__);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+u64_t db_insert_result(const char *sequence_identifier UNUSED)
+{
+ return dbi_conn_sequence_last(conn, UNUSED);
+}
+
+int db_query(const char *the_query)
+{
+ unsigned querysize = 0;
+ if (db_check_connection() < 0) {
+ trace(TRACE_ERROR, "%s,%s: no database connection",
+ __FILE__, __func__);
+ return -1;
+ }
+ if (the_query != NULL) {
+ querysize = (unsigned) strlen(the_query);
+ if (querysize > 0) {
+ trace(TRACE_DEBUG, "%s,%s: "
+ "executing query [%s]",
+ __FILE__, __func__, the_query);
+ result = dbi_conn_query(conn,
the_query);
+ if (result == NULL) {
+ trace(TRACE_ERROR, "%s,%s: "
+ "query [%s] failed",
+ __FILE__, __func__, the_query);
+ /* trace(TRACE_ERROR, "%s,%s: "
+ "mysql_real_query failed: %s",
+ __FILE__, __func__,
+ mysql_error(&conn)); // XXX TODO */
+ return -1;
+ }
+ } else {
+ trace(TRACE_ERROR, "%s,%s: "
+ "querysize is wrong: [%d]", __FILE__,
+ __func__, querysize);
+ return -1;
+ }
+ } else {
+ trace(TRACE_ERROR, "%s,%s: "
+ "query buffer is NULL, this is not supposed to happen\n",
+ __FILE__, __func__);
+ return -1;
+ }
+
+ //res = mysql_store_result(&conn);
+
+ return 0;
+}
+
+unsigned long db_escape_string(char *to,
+ const char *from, unsigned long length)
+{
+ // XXX TODO
+ // return dbi_driver_quote_string() or
dbi_driver_quote_string_copy() ??
+ return mysql_real_escape_string(&conn, to, from, length);
+}
+
+int db_do_cleanup(const char **tables, int num)
+{
+ // XXX TODO
+ char the_query[DEF_QUERYSIZE];
+ int i;
+ int result = 0;
+
+ for (i = 0; i < num; i++) {
+ snprintf(the_query, DEF_QUERYSIZE, "OPTIMIZE TABLE %s",
+ tables[i]);
+
+ if (db_query(the_query) == -1) {
+ trace(TRACE_ERROR,
+ "%s,%s: error optimizing table [%s]",
+ __FILE__, __func__, tables[i]);
+ result = -1;
+ }
+ db_free_result();
+ }
+ return result;
+}
+
+u64_t db_get_length(unsigned row, unsigned field)
+{
+ // XXX TODO
+ if (!res) {
+ trace(TRACE_WARNING, "%s,%s: result set is null\n",
+ __FILE__, __func__);
+ return -1;
+ }
+
+ if ((row >= db_num_rows()) || (field >= db_num_fields())) {
+ trace(TRACE_ERROR, "%s, %s: "
+ "row = %u, field = %u, bigger than size of result set",
+ __FILE__, __func__, row, field);
+ return -1;
+ }
+
+ mysql_data_seek(res, row);
+ last_row = mysql_fetch_row(res);
+ if (last_row == NULL) {
+ trace(TRACE_ERROR, "%s,%s: last_row = NULL",
+ __FILE__, __func__);
+ return (u64_t) 0;
+ }
+ return (u64_t) mysql_fetch_lengths(res)[field];
+}
+
+u64_t db_get_affected_rows()
+{
+ return dbi_result_get_numrows_affected(result);
+}
+
+void db_use_msgbuf_result()
+{
+ stored_result = result;
+ result = msgbuf_result;
+}
+
+void db_store_msgbuf_result()
+{
+ msgbuf_result = result;
+ result = stored_result;
+}
+
+void *db_get_result_set()
+{
+ return (void *) result;
+}
+
+void db_set_result_set(void *the_result_set)
+{
+ result = (dbi_result) the_result_set;
+}
signature.asc
Description: Digital signature
