/*************************************************************************** dataset.cpp (c) 2000-2009 BenoƮt Minisini 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, 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. ***************************************************************************/ /********************************************************************** * Copyright (c) 2002, Leo Seib, Hannover * * Project: C++ Dynamic Library * Module: Dataset abstraction later realisation file * Author: Leo Seib E-Mail: lev@almaty.pointstrike.net * Begin: 5/04/2002 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * **********************************************************************/ #include #include #include #include #include #include #include "dataset.h" extern "C" { //************* Database implementation *************** Database::Database() { active = false; // No connection yet error = ""; //S_NO_CONNECTION; host = ""; port = ""; db = ""; login = ""; passwd = ""; sequence_table = "db_sequence"; } Database::~Database() { disconnect(); // Disconnect if connected to database } int Database::connectFull(const char *newHost, const char *newPort, const char *newDb, const char *newLogin, const char *newPasswd) { host = newHost; port = newPort; db = newDb; login = newLogin; passwd = newPasswd; return connect(); } } //************* Dataset implementation *************** Dataset::Dataset() { db = NULL; haveError = active = false; frecno = 0; fbof = feof = true; autocommit = true; select_sql = ""; fields_object = new Fields(); edit_object = new Fields(); } Dataset::Dataset(Database * newDb) { db = newDb; haveError = active = false; frecno = 0; fbof = feof = true; autocommit = true; select_sql = ""; fields_object = new Fields(); edit_object = new Fields(); } Dataset::~Dataset() { update_sql.clear(); insert_sql.clear(); delete_sql.clear(); delete fields_object; delete edit_object; } void Dataset::setSqlParams(const char *sqlFrmt, sqlType t, ...) { va_list ap; char sqlCmd[DB_BUFF_MAX + 1]; va_start(ap, t); vsnprintf(sqlCmd, DB_BUFF_MAX - 1, sqlFrmt, ap); va_end(ap); switch (t) { case sqlSelect: set_select_sql(sqlCmd); break; case sqlUpdate: add_update_sql(sqlCmd); break; case sqlInsert: add_insert_sql(sqlCmd); break; case sqlDelete: add_delete_sql(sqlCmd); break; case sqlExec: sql = sqlCmd; break; } } void Dataset::set_select_sql(const char *sel_sql) { select_sql = sel_sql; } void Dataset::set_select_sql(const string & sel_sql) { select_sql = sel_sql; } void Dataset::parse_sql(string & sql) { string fpattern, by_what; pars.set_str(sql.c_str()); for (uint i = 0; i < fields_object->size(); i++) { fpattern = ":OLD_" + (*fields_object)[i].props.name; by_what = "'" + (*fields_object)[i].val.get_asString() + "'"; //cout << "parsing " << fpattern <size(); i++) { fpattern = ":NEW_" + (*edit_object)[i].props.name; by_what = "'" + (*edit_object)[i].val.get_asString() + "'"; sql = pars.replace(fpattern, by_what); } // StringList before_array, after_array; // int tag = 0; // bool eol_reached = false, // was_changed = false, // flag = false; // ExtString which_before, which_after; // ExtString bef, aft, prev_before, right_side, which_field, changed_field, f_value; // before_array.add(":NEW_", tag); // before_array.add(":OLD_", tag); // after_array.add(")", tag); // after_array.add(",", tag); // after_array.add(" ", tag); // sq.squish(); // bef = sq.before_arr(before_array, which_before); // while (!(bef == prev_before)) { // right_side = sq.after(which_before, flag); // right_side.squish(); // aft = right_side.after_arr(after_array, which_after); // aft.squish(); // which_field = right_side.before(which_after); // // checking whather we reach end of line // if ((which_field == "\0") && (which_before != "\0")) { // which_field = right_side; // eol_reached = true; // } // // If new field and is in insert or edit mode - looks in edit_object // if ((which_before == ":NEW_") && (which_field != "\0")) { // which_field.squish(); // f_value.assign(fv(which_field.getChars())); // f_value.addslashes(); // changed_field.assign("'"); // changed_field + f_value + "'"; // } // else // // else looking old value in the current result set // if ((which_before == ":OLD_") && (which_field != "\0")) { // which_field.squish(); // f_value.assign(f_old(which_field.getChars())); // f_value.addslashes(); // changed_field.assign("'"); // changed_field + f_value + "'"; // } // if (!eol_reached) { // sq.assign(bef + changed_field + which_after + aft); // } // else { // if (!was_changed && (which_field != "\0")) { // sq.assign(bef + changed_field + which_after + aft); // was_changed = true; // } // } // prev_before = bef; // bef = sq.before_arr(before_array, which_before); // } } void Dataset::close(void) { haveError = false; frecno = 0; fbof = feof = true; active = false; } //bool Dataset::seek(int pos=0) { bool Dataset::seek(int pos) { frecno = (pos < num_rows() - 1) ? pos : num_rows() - 1; frecno = (frecno < 0) ? 0 : frecno; fbof = feof = (num_rows() == 0) ? true : false; return frecno; } void Dataset::refresh() { int row = frecno; if ((row != 0) && active) { close(); open(); seek(row); } else open(); } void Dataset::first() { if (ds_state == dsSelect) { frecno = 0; feof = fbof = (num_rows() > 0) ? false : true; } } void Dataset::next() { if (ds_state == dsSelect) { fbof = false; if (frecno < num_rows() - 1) { frecno++; feof = false; } else feof = true; if (num_rows() <= 0) fbof = feof = true; } } void Dataset::prev() { if (ds_state == dsSelect) { feof = false; if (frecno) { frecno--; fbof = false; } else fbof = true; if (num_rows() <= 0) fbof = feof = true; } } void Dataset::last() { if (ds_state == dsSelect) { frecno = (num_rows() > 0) ? num_rows() - 1 : 0; feof = fbof = (num_rows() > 0) ? false : true; } } //bool Dataset::goto_rec(int pos=1) { bool Dataset::goto_rec(int pos) { if (ds_state == dsSelect) { return seek(pos - 1); } return false; } #if 0 void Dataset::insert() { //cout << "insert\n\n"; for (int i = 0; i < field_count(); i++) { (*fields_object)[i].val = ""; (*edit_object)[i].val = ""; //cout <<"Insert:"<size(); i++) { (*edit_object)[i].val = (*fields_object)[i].val; } ds_state = dsEdit; } void Dataset::post() { if (ds_state == dsInsert) make_insert(); else if (ds_state == dsEdit) make_edit(); } void Dataset::deletion() { if (ds_state == dsSelect) make_deletion(); } bool Dataset::set_field_value(const char *f_name, const field_value & value) { bool found = false; if ((ds_state == dsInsert) || (ds_state == dsEdit)) { for (uint i = 0; i < fields_object->size(); i++) if ((*edit_object)[i].props.name == f_name) { (*edit_object)[i].val = value; found = true; } if (!found) { GB.Error("Field not found: &1", f_name); } return found; } GB.Error("Not in Insert or Edit state"); return found; } const field_value & Dataset::get_field_value(const char *f_name) { static field_value fv; if (ds_state != dsInactive) { if (ds_state == dsEdit || ds_state == dsInsert) { for (uint i = 0; i < edit_object->size(); i++) if ((*edit_object)[i].props.name == f_name) return (*edit_object)[i].val; GB.Error("Field not found: %s", f_name); } else for (uint i = 0; i < fields_object->size(); i++) if ((*fields_object)[i].props.name == f_name) return (*fields_object)[i].val; GB.Error("Field not found: %s", f_name); } GB.Error("Dataset state is Inactive"); return fv; } const field_value & Dataset::get_field_value(int index) //const char *f_name) { static field_value fv; if (ds_state != dsInactive) { if (ds_state == dsEdit || ds_state == dsInsert) return (*edit_object)[index].val; else return (*fields_object)[index].val; } GB.Error("Dataset state is Inactive"); return fv; } const field_value Dataset::f_old(const char *f_name) { if (ds_state != dsInactive) for (uint i = 0; i < fields_object->size(); i++) if ((*fields_object)[i].props.name == f_name) return (*fields_object)[i].val; field_value fv; return fv; } void Dataset::setParamList(const ParamList & params) { plist = params; } bool Dataset::locate() { bool result; if (plist.empty()) return false; std::map < string, field_value >::const_iterator i; first(); while (!eof()) { result = true; for (i = plist.begin(); i != plist.end(); ++i) if (fv(i->first.c_str()).get_asString() == i->second.get_asString()) { continue; } else { result = false; break; } if (result) { return result; } next(); } return false; } bool Dataset::locate(const ParamList & params) { plist = params; return locate(); } bool Dataset::findNext(void) { bool result; if (plist.empty()) return false; std::map < string, field_value >::const_iterator i; while (!eof()) { result = true; for (i = plist.begin(); i != plist.end(); ++i) if (fv(i->first.c_str()).get_asString() == i->second.get_asString()) { continue; } else { result = false; break; } if (result) { return result; } next(); } return false; } void Dataset::add_update_sql(const char *upd_sql) { string s = upd_sql; update_sql.push_back(s); } void Dataset::add_update_sql(const string & upd_sql) { update_sql.push_back(upd_sql); } void Dataset::add_insert_sql(const char *ins_sql) { string s = ins_sql; insert_sql.push_back(s); } void Dataset::add_insert_sql(const string & ins_sql) { insert_sql.push_back(ins_sql); } void Dataset::add_delete_sql(const char *del_sql) { string s = del_sql; delete_sql.push_back(s); } void Dataset::add_delete_sql(const string & del_sql) { delete_sql.push_back(del_sql); } void Dataset::clear_update_sql() { update_sql.clear(); } void Dataset::clear_insert_sql() { insert_sql.clear(); } void Dataset::clear_delete_sql() { delete_sql.clear(); } int Dataset::field_count() { return fields_object->size(); } int Dataset::fieldCount() { return fields_object->size(); } const char *Dataset::fieldName(int n) { if (n < field_count() && n >= 0) return (*fields_object)[n].props.name.c_str(); else return NULL; } int Dataset::fieldSize(int n) { if (n < field_count() && n >= 0) return (*fields_object)[n].props.field_len; else return 0; } int Dataset::fieldIndex(const char *fn) { int index, length; if (strchr(fn, (int) '.')) { /* table name has been supplied */ for (uint i = 0; i < fields_object->size(); i++) { //if ((*fields_object)[i].props.name == fn) if (strcmp((*fields_object)[i].props.name.c_str(), fn) == 0) return i; } } else { for (uint i = 0; i < fields_object->size(); i++) { index = (*fields_object)[i].props.name.find('.') + 1; length = (*fields_object)[i].props.name.length(); /*printf("Field name [%s] find [%s] fn [%s]\n", (*fields_object)[i].props.name.c_str(), (*fields_object)[i].props.name.substr(index, length).c_str(), fn); */ //if ((*fields_object)[i].props.name.substr(index, length) == fn){ if (strcmp ((*fields_object)[i].props.name.substr(index, length).c_str(), fn) == 0) { return i; } } } return -1; } int Dataset::fieldType(int n) { if (n < field_count() && n >= 0) { //cout << (*fields_object)[n].val.gft(); return (*fields_object)[n].val.get_fType(); //return (*fields_object)[n].props.type; } else return 0; }