Revision 1 (by moose, 2006/03/06 10:00:33) Initial Import
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "MadSQLite.h"


MadSQLiteResult::MadSQLiteResult() { }
MadSQLiteResult::~MadSQLiteResult() { if(statement) sqlite3_finalize(statement); }

int MadSQLiteResult::reset()
{
	if(!statement)
		return MadDB_ERROR;

	sqlite3_reset(statement); // possibly do some error checking here.
	first = true;
	return MadDB_OK;
}

int MadSQLiteResult::step()
{
	if(statement == 0)
		return MadDB_ERROR;

	int status = sqlite3_step(statement);

	switch(status) {
		case SQLITE_BUSY:
			printf("step: BUSY\n");
			return MadDB_BUSY;

		case SQLITE_DONE:
			printf("step: DONE\n");
			return MadDB_DONE;

		case SQLITE_ROW:
			printf("step: ROW\n");
			return MadDB_ROW;

		case SQLITE_ERROR:
		case SQLITE_MISUSE:
		default:
			printf("step: ERROR (%i)\n", status);
			return MadDB_ERROR;
	}

	return MadDB_ERROR; // shouldn't get here, but what the hell, got to stop the compiler from bitching.
}

const void *MadSQLiteResult::columnBlob(int col)
{
	if(statement == 0)
		return 0;

	return sqlite3_column_blob(statement, col);
}

int MadSQLiteResult::columnBytes(int col)
{
	if(statement == 0)
		return -1;

	return sqlite3_column_bytes(statement, col);
}

double MadSQLiteResult::columnDouble(int col)
{
	if(statement == 0)
		return 0.0;

	return sqlite3_column_double(statement, col);
}

int MadSQLiteResult::columnInt(int col)
{
	if(statement == 0)
		return -1;

	return sqlite3_column_int(statement, col);
}

const char *MadSQLiteResult::columnText(int col)
{
	if(statement == 0)
		return 0;

	return (const char *)sqlite3_column_text(statement, col);
}

int MadSQLiteResult::columnType(int col)
{
	if(!statement)
		return MadDB_ERROR;

	switch(sqlite3_column_type(statement, col)) {
		case SQLITE_INTEGER: return MadDB_INTEGER;
		case SQLITE_FLOAT:   return MadDB_FLOAT;
		case SQLITE_TEXT:    return MadDB_TEXT;
		case SQLITE_BLOB:    return MadDB_BLOB;
		case SQLITE_NULL:    return MadDB_NULL;
	}

	return MadDB_ERROR;
}

int MadSQLiteResult::columnCount()
{
	return sqlite3_data_count(statement);
}



int MadSQLiteResult::bindBlob(int idx, const void *blob, int n)
{
	sqlite3_bind_blob(statement, idx, blob, n, SQLITE_TRANSIENT);
	return MadDB_OK;
}

int MadSQLiteResult::bindDouble(int idx, double dbl)
{
	sqlite3_bind_double(statement, idx, dbl);
	return MadDB_OK;
}

int MadSQLiteResult::bindInt(int idx, int i)
{
	sqlite3_bind_int(statement, idx, i);
	return MadDB_OK;
}

int MadSQLiteResult::bindNull(int idx)
{
	sqlite3_bind_null(statement, idx);
	return MadDB_OK;
}

int MadSQLiteResult::bindText(int idx, const char *text)
{
	sqlite3_bind_text(statement, idx, text, strlen(text), SQLITE_TRANSIENT);
	return MadDB_OK;
}


//

bool MadSQLite::connect()
{
	int status = sqlite3_open(dbname, &handle);
	if(status != SQLITE_OK)
		return false;

	sqlite3_busy_timeout(handle, 200);
	
	return true;
}

bool MadSQLite::disconnect()
{
	if(sqlite3_close(handle)!=SQLITE_OK) {
		printf("failed to close sqlite: %s\n", error_message());
		return false;
	}
	
	return true;
}

// transactions
bool MadSQLite::begin()
{
	if(transaction++)
		return true;

	return query("BEGIN TRANSACTION;");
}

bool MadSQLite::commit()
{
	if(!--transaction)
		return query("COMMIT;");

	return true;
}

bool MadSQLite::rollback()
{
	if(!--transaction)
		return query("ROLLBACK;");

	return true;
}


MadSQLiteResult *MadSQLite::prepare(const char *sql)
{
	if(!handle) return 0;

//	printf("prepare: \"%s\"\n", sql);

	MadSQLiteResult *result = new MadSQLiteResult();
	const char *unused = 0;

	int status = 0;
	
	do {
		status = sqlite3_prepare(handle, sql, strlen(sql), &(result->statement), &unused);
	} while(status == SQLITE_BUSY);
	
	if(status != SQLITE_OK) {
		printf("prepare error: %s\n", error_message());
		return 0;
	}
	
	return result;
}

MadSQLiteResult *MadSQLite::preparef(const char *fmt, ...)
{
	va_list ap;
	char *sql = 0;
	MadSQLiteResult *res = 0;

	va_start(ap, fmt);
	sql = sqlite3_vmprintf(fmt, ap);
	va_end(ap);

	res = prepare(sql);

	sqlite3_free(sql);

	return res;
}

bool MadSQLite::query(const char *sql)
{
	MadSQLiteResult *result = prepare(sql);
	if(result == 0)
		return false;

	int res = false;

	do {
		res = result->step();
	} while(res == MadDB_ROW);

	delete result;

	if(res != MadDB_DONE)
		return false;

	return true;
}

bool MadSQLite::queryf(const char *fmt, ...)
{
	va_list ap;
	char *sql = 0;
	bool res = false;

	va_start(ap, fmt);
	sql = sqlite3_vmprintf(fmt, ap);
	va_end(ap);

	res = query(sql);

	sqlite3_free(sql);

	return res;
}

int MadSQLite::last_insert_id()
{
	return sqlite3_last_insert_rowid(handle);
}

const char *MadSQLite::error_message()
{
	return sqlite3_errmsg(handle);
}