I've cobbled together what I think is 80-90% support for an SQLite
driver.

I'd like some assistance getting it into CVS and getting the various
autoconf nonsense set up so it doesn't depend on postgres/mysql.

I have not tested it yet, so perhaps the best thing to do is to setup a
way that we can --disable-builtin-dbs so I can build it outside of
dbmail.

Will hack more tomorrow...

-- 
Internet Connection High Quality Web Hosting
http://www.internetconnection.net/
/*
  Copyright (C) 2005 Internet Connection, Inc.

  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License 
  as published by the Free Software Foundation; either 
  version 2 of the License, or (at your option) any later 
  version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/**
 * dbsqlite.c
 * SQLite driver file
 * Manages access to an SQLite2/3 database
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "db.h"
#include "dbmail.h"
#include "dbmailtypes.h"

#include <sqlite.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

db_param_t _db_params;

/* native format is the character string */
const char *TO_CHAR = "%s";
const char *TO_DATE = "%s";

static sqlite *conn;

struct qtmp {
	char **resp;
	unsigned int rows, cols;
};

struct qtmp *lastq = 0, *saveq = 0, *tempq = 0;

int db_connect()
{
	char *errmsg;
	if (!(conn = sqlite_open(_db_params.db, 0600, &errmsg))) {
		trace(TRACE_ERROR,
		      "%si,%s: sqlite_open failed: %s",
		      __FILE__, __func__, errmsg);
		sqlite_freemem(errmsg);
		return -1;
	}
	return 0;
}

int db_check_connection()
{
	return 0;
}
void db_free_result()
{
	if (lastq) {
		if (lastq->resp) sqlite_free_table(lastq->resp);
		lastq->resp = 0;
		lastq->rows = lastq->cols = 0;
		free(lastq);
	}
	lastq = 0;

}
int db_disconnect()
{
	db_free_result();

	db_store_msgbuf_result();
	db_free_result();

	db_use_msgbuf_result();
	db_free_result();

	sqlite_close(conn);
	conn = 0;
	return 0;
}
unsigned db_num_rows()
{
	return lastq ? lastq->rows : 0;
}
unsigned db_num_fields()
{
	return lastq ? lastq->cols : 0;
}

const char *db_get_result(unsigned row, unsigned field)
{
	if (!lastq || !lastq->resp || !lastq->resp[row]) return NULL;
	return lastq->resp[((row+1) * lastq->cols) + field];
}

u64_t db_insert_result(const char *sequence_identifier UNUSED)
{
	if (!conn) return 0;
	return (u64_t)sqlite_last_insert_rowid(conn);
}

int db_query(const char *the_query)
{
	char *errmsg;

	if (lastq) {
		if (lastq->resp) sqlite_free_table(lastq->resp);
	} else {
		lastq = (struct qtmp *)malloc(sizeof(struct qtmp));
		if (!lastq) {
			trace(TRACE_ERROR,
			      "%si,%s: malloc failed: %s",
			      __FILE__, __func__, strerror(errno));
		}
	}

	if (sqlite_get_table(conn, the_query, &lastq->resp,
			&lastq->rows, &lastq->cols, &errmsg) != SQLITE_OK) {
		trace(TRACE_ERROR,
		      "%si,%s: sqlite_exec failed: %s",
		      __FILE__, __func__, errmsg);
		sqlite_freemem(errmsg);
		return -1;
	}
}
unsigned long db_escape_string(char *to, const char *from, unsigned long length)
{
	unsigned long did = 0;
	while (length > 0) {
		if (*from == '\'') *to++ = *from;
		*to++ = *from;
		length--;
		did++;
	}
	return did;
}
int db_do_cleanup(const char **tables UNUSED, int num_tables UNUSED)
{
	char *errmsg;
	if (!conn) return -1;
	if (sqlite_exec(conn, "VACUUM", NULL, NULL, &errmsg) != SQLITE_OK) {
		trace(TRACE_ERROR,
		      "%s,%s: error vacuuming database: %s",
		      __FILE__, __func__, errmsg);
		return -1;
	}
	return 0;
}
u64_t db_get_length(unsigned row, unsigned field)
{
	const char *q = db_get_result(row,field);
	return (u64_t)strlen(q ? q : "");
}
u64_t db_get_affected_rows()
{
	if (!conn) return 0;
	return (u64_t)sqlite_changes(conn);
}

void db_use_msgbuf_result()
{
	saveq = lastq;
	lastq = tempq;
}

void db_store_msgbuf_result()
{
	tempq = lastq;
	lastq = saveq;
}

void *db_get_result_set()
{
	return (void*)lastq;
}

void db_set_result_set(void *the_result_set)
{
	db_free_result();
	lastq = (struct qtmp *)the_result_set;
}

Reply via email to