gambas-source-code/gb.db.sqlite2/src/dataset.cpp
Benoît Minisini 2fbf67cb29 [CONFIGURATION]
* NEW: Update FSF address in every source file.


git-svn-id: svn://localhost/gambas/trunk@3870 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2011-06-03 00:51:09 +00:00

584 lines
14 KiB
C++

/***************************************************************************
dataset.cpp
(c) 2000-2011 Benoît Minisini <gambas@users.sourceforge.net>
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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, 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 <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <time.h>
#include <iostream>
#include <string.h>
#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 <<by_what<<"\n\n";
sql = pars.replace(fpattern,by_what);
}
for (uint i=0;i< edit_object->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;
}
/*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:"<<i<<"\n\n";
}
ds_state = dsInsert;
}*/
void Dataset::edit() {
if (ds_state != dsSelect) {
cerr<<"Editing is possible only when query exists!";
return;
}
for (uint i=0; i<fields_object->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;
}