#include "TSQLiteServer.h"
#include "TSQLiteResult.h"
#include "TSQLiteStatement.h"
#include "TSQLColumnInfo.h"
#include "TList.h"
#include "TSQLTableInfo.h"
#include "TSQLRow.h"
ClassImp(TSQLiteServer)
TSQLiteServer::TSQLiteServer(const char *db, const char* , const char* )
{
fSQLite = NULL;
fSrvInfo = "SQLite ";
fSrvInfo += sqlite3_libversion();
if (strncmp(db, "sqlite://", 9)) {
TString givenProtocol(db, 9);
Error("TSQLiteServer", "protocol in db argument should be sqlite it is %s",
givenProtocol.Data());
MakeZombie();
return;
}
const char *dbase = db + 9;
#ifndef SQLITE_OPEN_URI
#define SQLITE_OPEN_URI 0x00000000
#endif
#if SQLITE_VERSION_NUMBER >= 3005000
Int_t error = sqlite3_open_v2(dbase, &fSQLite, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
#else
Int_t error = sqlite3_open(dbase, &fSQLite);
#endif
if (error == 0) {
fType = "SQLite";
fHost = "";
fDB = dbase;
fPort = 0;
} else {
Error("TSQLiteServer", "opening of %s failed with error: %d %s", dbase, sqlite3_errcode(fSQLite), sqlite3_errmsg(fSQLite));
sqlite3_close(fSQLite);
MakeZombie();
}
}
TSQLiteServer::~TSQLiteServer()
{
if (IsConnected()) {
sqlite3_close(fSQLite);
}
}
void TSQLiteServer::Close(Option_t *)
{
if (!fSQLite) {
return;
}
if (IsConnected()) {
sqlite3_close(fSQLite);
fPort = -1;
fSQLite = NULL;
}
}
Bool_t TSQLiteServer::StartTransaction()
{
return Exec("BEGIN TRANSACTION");
}
TSQLResult *TSQLiteServer::Query(const char *sql)
{
if (!IsConnected()) {
Error("Query", "not connected");
return 0;
}
sqlite3_stmt *preparedStmt = NULL;
#if SQLITE_VERSION_NUMBER >= 3005000
int retVal = sqlite3_prepare_v2(fSQLite, sql, -1, &preparedStmt, NULL);
#else
int retVal = sqlite3_prepare(fSQLite, sql, -1, &preparedStmt, NULL);
#endif
if (retVal != SQLITE_OK) {
Error("Query", "SQL Error: %d %s", retVal, sqlite3_errmsg(fSQLite));
return 0;
}
return new TSQLiteResult(preparedStmt);
}
Bool_t TSQLiteServer::Exec(const char *sql)
{
if (!IsConnected()) {
Error("Exec", "not connected");
return kFALSE;
}
char *sqlite_err_msg;
int ret = sqlite3_exec(fSQLite, sql, NULL, NULL, &sqlite_err_msg);
if (ret != SQLITE_OK) {
Error("Exec", "SQL Error: %d %s", ret, sqlite_err_msg);
sqlite3_free(sqlite_err_msg);
return kFALSE;
}
return kTRUE;
}
Int_t TSQLiteServer::SelectDataBase(const char* )
{
Error("SelectDataBase", "SelectDataBase command makes no sense for SQLite!");
return -1;
}
TSQLResult *TSQLiteServer::GetDataBases(const char* )
{
Error("GetDataBases", "GetDataBases command makes no sense for SQLite!");
return 0;
}
TSQLResult *TSQLiteServer::GetTables(const char* , const char *wild)
{
if (!IsConnected()) {
Error("GetTables", "not connected");
return 0;
}
TString sql = "SELECT name FROM sqlite_master where type='table'";
if (wild)
sql += Form(" AND name LIKE '%s'", wild);
return Query(sql);
}
TSQLResult *TSQLiteServer::GetColumns(const char* , const char* table,
const char* wild)
{
if (!IsConnected()) {
Error("GetColumns", "not connected");
return 0;
}
if (wild) {
Error("GetColumns", "Not implementable for SQLite as a query with wildcard, use GetFieldNames() after SELECT instead!");
return NULL;
} else {
TString sql = Form("PRAGMA table_info('%s')", table);
return Query(sql);
}
}
TSQLTableInfo *TSQLiteServer::GetTableInfo(const char* tablename)
{
if (!IsConnected()) {
Error("GetTableInfo", "not connected");
return 0;
}
if ((tablename==0) || (*tablename==0)) return 0;
TSQLResult *columnRes = GetColumns("", tablename);
if (columnRes == NULL) {
Error("GetTableInfo", "could not query columns");
return NULL;
}
TList* lst = NULL;
TSQLRow *columnRow;
while ((columnRow = columnRes->Next()) != NULL) {
if (lst == NULL) {
lst = new TList();
}
Bool_t isNullable = (strcmp(columnRow->GetField(3), "0") == 0);
lst->Add(new TSQLColumnInfo(columnRow->GetField(1),
columnRow->GetField(2),
isNullable,
-1,
-1,
-1,
-1,
-1));
delete columnRow;
}
delete columnRes;
TSQLTableInfo* info = new TSQLTableInfo(tablename,
lst);
return info;
}
Int_t TSQLiteServer::CreateDataBase(const char* )
{
Error("CreateDataBase", "CreateDataBase command makes no sense for SQLite!");
return -1;
}
Int_t TSQLiteServer::DropDataBase(const char* )
{
Error("DropDataBase", "DropDataBase command makes no sense for SQLite!");
return -1;
}
Int_t TSQLiteServer::Reload()
{
if (!IsConnected()) {
Error("Reload", "not connected");
return -1;
}
Error("Reload", "not implemented");
return 0;
}
Int_t TSQLiteServer::Shutdown()
{
if (!IsConnected()) {
Error("Shutdown", "not connected");
return -1;
}
Error("Shutdown", "not implemented");
return -1;
}
Bool_t TSQLiteServer::HasStatement() const
{
return kTRUE;
}
TSQLStatement* TSQLiteServer::Statement(const char *sql, Int_t)
{
if (!sql || !*sql) {
SetError(-1, "no query string specified", "Statement");
return 0;
}
if (!IsConnected()) {
Error("Statement", "not connected");
return 0;
}
sqlite3_stmt *preparedStmt = NULL;
#if SQLITE_VERSION_NUMBER >= 3005000
int retVal = sqlite3_prepare_v2(fSQLite, sql, -1, &preparedStmt, NULL);
#else
int retVal = sqlite3_prepare(fSQLite, sql, -1, &preparedStmt, NULL);
#endif
if (retVal != SQLITE_OK) {
Error("Statement", "SQL Error: %d %s", retVal, sqlite3_errmsg(fSQLite));
return 0;
}
SQLite3_Stmt_t *stmt = new SQLite3_Stmt_t;
stmt->fConn = fSQLite;
stmt->fRes = preparedStmt;
return new TSQLiteStatement(stmt);
}
const char *TSQLiteServer::ServerInfo()
{
if (!IsConnected()) {
Error("ServerInfo", "not connected");
return 0;
}
return fSrvInfo.Data();
}