#include <qvaluelist.h>
#include "MadConf.h"
#include "MadException.h"
const char sql_create_key_table[] =
"CREATE TABLE conf_key ("
"id INTEGER PRIMARY KEY,"
"parent_id INTEGER,"
"type_id INTEGER,"
"name TEXT"
");";
const char sql_create_data_table[] =
"CREATE TABLE conf_data ("
"id INTEGER PRIMARY KEY,"
"key_id INTEGER KEY,"
"data TEXT"
");";
const char sql_create_data_opt_table[] =
"CREATE TABLE conf_data_opt ("
"id INTEGER PRIMARY KEY,"
"key_id INTEGER KEY,"
"data TEXT"
");";
/****************** MadConfKeyValue ******************/
bool MadConfKeyValue::set(int i)
{
value.setNum(i);
return conf->db->queryf("UPDATE conf_data SET data='%i' WHERE id=%i;", i, id);
}
bool MadConfKeyValue::set(bool b)
{
value.setNum((int)b);
return conf->db->queryf("UPDATE conf_data SET data='%i' WHERE id=%i;", (int)b, id);
}
bool MadConfKeyValue::set(const char *s)
{
value = s;
return conf->db->queryf("UPDATE conf_data SET data='%q' WHERE id=%i;", s, id);
}
bool MadConfKeyValue::set(double d)
{
value.setNum(d);
return conf->db->queryf("UPDATE conf_data SET data='%f' WHERE id=%i;", d, id);
}
void MadConfKeyValue::erase()
{
//printf("erasing: %i\n", id);
conf->db->queryf("DELETE FROM conf_data WHERE id=%i;", id);
}
/****************** MadConfKeyOpt ******************/
bool MadConfKeyOpt::set(int i)
{
value.setNum(i);
return conf->db->queryf("UPDATE conf_data_opt SET data='%i' WHERE id=%i;", i, id);
}
bool MadConfKeyOpt::set(bool b)
{
value.setNum((int)b);
return conf->db->queryf("UPDATE conf_data_opt SET data='%i' WHERE id=%i;", (int)b, id);
}
bool MadConfKeyOpt::set(const char *s)
{
value = s;
return conf->db->queryf("UPDATE conf_data_opt SET data='%q' WHERE id=%i;", s, id);
}
bool MadConfKeyOpt::set(double d)
{
value.setNum(d);
return conf->db->queryf("UPDATE conf_data_opt SET data='%f' WHERE id=%i;", d, id);
}
void MadConfKeyOpt::erase()
{
//printf("erasing: %i\n", id);
conf->db->queryf("DELETE FROM conf_data_opt WHERE id=%i;", id);
}
/****************** MadConfKey ******************/
bool MadConfKey::AUTO_COMMIT;
MadConfKey::MadConfKey(MadConf *c, int i, int t, const char *k) : key(k), id(i), type(t), conf(c), value_result(0), child_result(0), opt_result(0)
{
printf("MadConfKey(): %s(%i)\n", (const char *)key, id);
}
MadConfKey::~MadConfKey()
{
printf("~MadConfKey(): %s(%i)\n", (const char *)key, id);
if(value_result)
delete value_result;
if(child_result)
delete child_result;
if(opt_result)
delete opt_result;
}
bool MadConfKey::setName(const char *k)
{
key = QString(k);
bool ret = conf->db->queryf("UPDATE conf_key SET name='%q' WHERE id=%i", k, id);
if(!ret)
printf("err: %s\n", conf->db->error_message());
return ret;
}
bool MadConfKey::setType(int t)
{
type = t;
return conf->db->queryf("UPDATE conf_key SET type_id=%i WHERE id=%i", t, id);
}
QString MadConfKey::name()
{
MadSQLiteResult *res = conf->db->preparef("SELECT name FROM conf_key WHERE id=%i;", id);
if(!res)
return QString("");
if(res->step() == MadDB_ROW) {
QString tmp(res->columnText(0));
delete res;
return tmp;
}
delete res;
return QString("");
}
bool MadConfKey::insert_key()
{
bool res = conf->db->queryf("INSERT INTO conf_key (parent_id, type_id, name) VALUES (%i, %i, '%q');", id, type, (const char *)key);
id = conf->db->last_insert_id();
return res;
}
bool MadConfKey::value(MadConfKeyValue &v)
{
printf("value()\n");
if(value_result)
delete value_result;
value_result = conf->db->preparef("SELECT d.id,d.data FROM conf_key k INNER JOIN conf_data d ON k.id=d.key_id WHERE k.id=%i;", id);
if(!value_result)
return false;
if(value_result->step() != MadDB_ROW) {
printf("~value(): %s(%i)\n", (const char *)key, id);
delete value_result;
value_result = 0;
return false;
}
v = MadConfKeyValue(conf, value_result->columnInt(0), value_result->columnText(1));
delete value_result;
value_result = 0;
return true;
}
bool MadConfKey::beginValue()
{
printf("beginValue\n");
if(value_result)
delete value_result;
value_result = conf->db->preparef("SELECT d.id,d.data FROM conf_key k INNER JOIN conf_data d ON k.id=d.key_id WHERE k.id=%i;", id);
if(!value_result)
return false;
return true;
}
bool MadConfKey::step(MadConfKeyValue &v)
{
// printf("step (v)\n");
if(!value_result)
return false;
if(value_result->step() != MadDB_ROW) {
printf("~step(value): %s(%i)\n", (const char *)key, id);
delete value_result;
value_result = 0;
return false;
}
v = MadConfKeyValue(conf, value_result->columnInt(0), value_result->columnText(1));
return true;
}
bool MadConfKey::addValue(MadConfKeyValue &v, const char *txt)
{
if(type && type != MCKT_VALUE && type != MCKT_VALUE_LIST) {
MadConfKeyOpt opt;
beginOpt();
while(step(opt)) {
if(opt.value == QString(txt)) {
bool result = conf->db->queryf("INSERT INTO conf_data (key_id,data) VALUES (%i,'%q')", id, txt);
if(!result)
return false;
v = MadConfKeyValue(conf, conf->db->last_insert_id(), txt);
return true;
}
}
return false;
}
else {
bool result = conf->db->queryf("INSERT INTO conf_data (key_id,data) VALUES (%i,'%q')", id, txt);
if(!result)
return false;
v = MadConfKeyValue(conf, conf->db->last_insert_id(), txt);
}
return true;
}
/*
MadConfKey *MadConfKey::getParent()
{
MadSQLiteResult *result = conf->db->preparef("SELECT id,type_id,name FROM conf_key
}
*/
//MadConfKey *newChild(const char *keyname, int type = MCKT_VALUE);
bool MadConfKey::newChild(MadConfKey &k, const char *keyname, int type)
{
k = MadConfKey(conf, id, type, keyname);
if(!k.insert_key())
return false;
return true;
}
bool MadConfKey::beginChild()
{
printf("beginChild\n");
if(child_result)
delete child_result;
child_result = conf->db->preparef("SELECT id,type_id,name FROM conf_key WHERE parent_id=%i;", id);
if(!child_result)
return false;
return true;
}
bool MadConfKey::step(MadConfKey &k)
{
// printf("step (k)\n");
if(!child_result)
return false;
if(child_result->step() != MadDB_ROW) {
printf("~step(key): %s(%i)\n", (const char *)key, id);
delete child_result;
child_result = 0;
return false;
}
k = MadConfKey(conf, child_result->columnInt(0), child_result->columnInt(1), child_result->columnText(2));
return true;
}
bool MadConfKey::child(MadConfKey &key, const char *k)
{
// printf("child()\n");
if(child_result)
delete child_result;
child_result = conf->db->preparef("SELECT id,type_id FROM conf_key WHERE parent_id=%i AND name='%q';", id, k);
if(!child_result)
return false;
if(child_result->step() != MadDB_ROW) {
printf("~child(): %s(%i)\n", (const char *)this->key, id);
delete child_result;
child_result = 0;
return false;
}
key = MadConfKey(conf, child_result->columnInt(0), child_result->columnInt(1), k);
delete child_result;
child_result = 0;
return true;
}
bool MadConfKey::beginOpt()
{
printf("beginOpt\n");
if(opt_result)
delete opt_result;
opt_result = conf->db->preparef("SELECT d.id,d.data FROM conf_key k INNER JOIN conf_data_opt d ON k.id=d.key_id WHERE k.id=%i;", id);
if(!opt_result)
return false;
return true;
}
bool MadConfKey::step(MadConfKeyOpt &v)
{
// printf("step (v)\n");
if(!opt_result)
return false;
if(opt_result->step() != MadDB_ROW) {
printf("~step(opt): %s(%i)\n", (const char *)key, id);
delete opt_result;
opt_result = 0;
return false;
}
v = MadConfKeyOpt(conf, opt_result->columnInt(0), opt_result->columnText(1));
return true;
}
bool MadConfKey::addOpt(MadConfKeyOpt &v, const char *txt)
{
if(!type || type == MCKT_VALUE || type == MCKT_VALUE_LIST)
return false;
bool result = conf->db->queryf("INSERT INTO conf_data_opt (key_id,data) VALUES (%i,'%q')", id, txt);
if(!result)
return false;
v = MadConfKeyOpt(conf, conf->db->last_insert_id(), txt);
return true;
}
bool MadConfKey::delete_key(int kid)
{
typedef QValueList<int> intlist;
intlist idlist;
printf("delete_key(%i)\n", kid);
MadSQLiteResult *res = conf->db->preparef("SELECT id FROM conf_key WHERE parent_id=%i;", kid);
if(!res)
return false;
while(res->step() == MadDB_ROW) {
idlist.append(res->columnInt(0));
}
delete res;
intlist::iterator it;
for(it=idlist.begin(); it != idlist.end(); ++it)
if(!delete_key(*it))
return false;
bool r = conf->db->queryf("DELETE FROM conf_key WHERE id=%i;", id);
if(!r) {
printf("failed key: %s\n", conf->db->error_message());
return false;
}
printf("DELETE KEY\n");
r = conf->db->queryf("DELETE FROM conf_data WHERE key_id=%i;", id);
if(!r) {
printf("failed data: %s\n", conf->db->error_message());
return false;
}
printf("DELETE DATA\n");
r = conf->db->queryf("DELETE FROM conf_data_opt WHERE key_id=%i;", id);
if(!r) {
printf("failed opt: %s\n", conf->db->error_message());
return false;
}
printf("DELETE DATA OPT\n");
return true;
}
bool MadConfKey::erase()
{
printf("erase\n");
conf->db->begin();
if(!delete_key(id)) {
conf->db->rollback();
return false;
}
conf->db->commit();
printf("end erase\n");
return true;
}
MadConf::MadConf(const char *name) : result(0)
{
db = new MadSQLite();
db->database(name);
if(!db->connect()) {
const char *msg = db->error_message();
delete db;
mad_throw(MadException, msg);
}
if(!initDB())
mad_throw(MadException, db->error_message());
}
MadConf::~MadConf()
{
if(result)
delete result;
if(db)
delete db;
}
bool MadConf::beginKey()
{
result = db->prepare("SELECT id,type_id,name FROM conf_key WHERE parent_id = 0;");
if(!result)
return false;
return true;
}
bool MadConf::step(MadConfKey &k)
{
if(!result)
return false;
if(result->step() != MadDB_ROW) {
delete result;
result = 0;
return false;
}
k = MadConfKey(this, result->columnInt(0), result->columnInt(1), result->columnText(2));
return true;
}
bool MadConf::key(MadConfKey &k, int id)
{
MadSQLiteResult *result = 0;
result = db->preparef("SELECT type_id,name FROM conf_key WHERE id=%i;", id);
if(!result)
return MadConfKey();
if(result->step() != MadDB_ROW) {
delete result;
return MadConfKey();
}
k = MadConfKey(this, id, result->columnInt(0), result->columnText(1));
delete result;
result = 0;
return true;
}
bool MadConf::key(MadConfKey &k, const char *key)
{
MadSQLiteResult *result = 0;
result = db->preparef("SELECT id,type_id,name FROM conf_key WHERE name='%q';", key);
if(!result)
return MadConfKey();
if(result->step() != MadDB_ROW) {
delete result;
return MadConfKey();
}
k = MadConfKey(this, result->columnInt(0), result->columnInt(1), result->columnText(2));
delete result;
result = 0;
return true;
}
bool MadConf::newKey(MadConfKey &k, const char *keyname, int type)
{
k = MadConfKey(this, 0, type, keyname);
if(!k.insert_key())
return false;
return true;
}
bool MadConf::initDB()
{
bool seen_key = false, seen_data = false, seen_data_opt = false;
db->begin();
MadSQLiteResult *result = db->prepare("SELECT tbl_name FROM sqlite_master WHERE type='table';");
if(!result) {
printf("prepare failed: '%s'\n", db->error_message());
db->rollback();
return false;
}
while(1) {
int res = result->step();
if(res != MadDB_ROW)
break;
const char *table = (const char *)result->columnText(0);
printf("table: '%s'\n", table);
if(strcmp(table, "conf_key") == 0) {
seen_key = true;
continue;
}
if(strcmp(table, "conf_data") == 0) {
seen_data = true;
continue;
}
if(strcmp(table, "conf_data_opt") == 0) {
seen_data_opt = true;
continue;
}
}
delete result;
if(seen_key == false) {
int status = db->query(sql_create_key_table);
if(status != MadDB_OK) {
db->rollback();
return false;
}
}
if(seen_data == false) {
int status = db->query(sql_create_data_table);
if(status != MadDB_OK) {
db->rollback();
return false;
}
}
if(seen_data_opt == false) {
int status = db->query(sql_create_data_opt_table);
if(status != MadDB_OK) {
db->rollback();
return false;
}
}
db->commit();
return true;
}