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