|
#include <Wt/WApplication>
|
|
#include <Wt/WLogger>
|
|
#include "mir_firebird.h"
|
|
|
|
//#include "mir_exception.h"
|
|
#include "Wt/Dbo/Exception"
|
|
|
|
#include <Wt/Dbo/SqlConnection>
|
|
#include <Wt/Dbo/SqlStatement>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <sstream>
|
|
|
|
#include <unicode/fmtable.h>
|
|
#include <unicode/msgfmt.h>
|
|
|
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
#include <boost/date_time/gregorian/gregorian.hpp>
|
|
#include <boost/date_time/posix_time/time_parsers.hpp>
|
|
|
|
#ifdef WIN32
|
|
#define snprintf _snprintf
|
|
#define strcasecmp _stricmp
|
|
#endif
|
|
|
|
#define BYTEAOID 17
|
|
|
|
//#define DEBUG(x) x
|
|
#define DEBUG(x)
|
|
|
|
#include <ibpp.h>
|
|
|
|
namespace SyNaT
|
|
{
|
|
namespace MIR
|
|
{
|
|
|
|
using namespace Wt::Dbo;
|
|
using namespace Wt;
|
|
|
|
class FirebirdException : public Wt::Dbo::Exception
|
|
{
|
|
public:
|
|
FirebirdException(const std::string& msg)
|
|
: Wt::Dbo::Exception(msg)
|
|
{ }
|
|
};
|
|
|
|
class FirebirdStatement : public SqlStatement
|
|
{
|
|
public:
|
|
FirebirdStatement(Firebird& conn, const std::string& sql)
|
|
: conn_(conn),
|
|
sql_(convertToNumberedPlaceholders(sql))
|
|
{
|
|
lastId_ = -1;
|
|
row_ = affectedRows_ = 0;
|
|
//result_ = 0;
|
|
|
|
paramValues_ = 0;
|
|
paramTypes_ = paramLengths_ = paramFormats_ = 0;
|
|
|
|
this->m_stmt = 0;
|
|
|
|
snprintf(name_, 64, "SQL%p%08X", this, rand());
|
|
|
|
DEBUG(std::cerr << this << " for: " << sql_ << std::endl);
|
|
|
|
Transaction tr = conn_.transaction();
|
|
// if (!this->m_stmt)
|
|
// {
|
|
m_stmtnp = conn_.connection()->createStatement(&tr);
|
|
this->m_stmt = &m_stmtnp;
|
|
// }
|
|
//(*this->m_stmt)->TransactionPtr().
|
|
try
|
|
{
|
|
(*this->m_stmt)->Prepare(sql_);
|
|
// wApp->log("info") << sql_;
|
|
}
|
|
catch(IBPP::LogicException &e)
|
|
{
|
|
throw FirebirdException(e.what());
|
|
}
|
|
|
|
state_ = Done;
|
|
}
|
|
|
|
virtual ~FirebirdStatement()
|
|
{
|
|
//PQclear(result_);
|
|
if (paramValues_)
|
|
delete[] paramValues_;
|
|
if (paramTypes_)
|
|
delete[] paramTypes_;
|
|
}
|
|
|
|
virtual void reset()
|
|
{
|
|
state_ = Done;
|
|
}
|
|
|
|
virtual void bind(int column, const std::string& value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " " << value << std::endl);
|
|
|
|
setValue(column, value);
|
|
}
|
|
|
|
virtual void bind(int column, short value)
|
|
{
|
|
bind(column, static_cast<int>(value));
|
|
}
|
|
|
|
virtual void bind(int column, int value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " " << value << std::endl);
|
|
|
|
setValue(column, boost::lexical_cast<std::string>(value));
|
|
}
|
|
|
|
virtual void bind(int column, long long value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " " << value << std::endl);
|
|
|
|
setValue(column, boost::lexical_cast<std::string>(value));
|
|
}
|
|
|
|
virtual void bind(int column, float value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " " << value << std::endl);
|
|
|
|
setValue(column, boost::lexical_cast<std::string>(value));
|
|
}
|
|
|
|
virtual void bind(int column, double value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " " << value << std::endl);
|
|
|
|
setValue(column, boost::lexical_cast<std::string>(value));
|
|
}
|
|
|
|
virtual void bind(int column, const boost::posix_time::time_duration & value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " " << boost::posix_time::to_simple_string(value) << std::endl);
|
|
|
|
std::string v = boost::posix_time::to_simple_string(value);
|
|
|
|
setValue(column, v);
|
|
}
|
|
|
|
virtual void bind(int column, const boost::posix_time::ptime& value,
|
|
SqlDateTimeType type)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " "
|
|
<< boost::posix_time::to_simple_string(value) << std::endl);
|
|
|
|
std::string v;
|
|
if (type == SqlDate)
|
|
v = boost::gregorian::to_iso_extended_string(value.date());
|
|
else
|
|
{
|
|
v = boost::posix_time::to_iso_extended_string(value);
|
|
v[v.find('T')] = ' ';
|
|
}
|
|
|
|
setValue(column, v);
|
|
}
|
|
|
|
virtual void bind(int column, const std::vector<unsigned char>& value)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " (blob, size=" <<
|
|
value.size() << ")" << std::endl);
|
|
|
|
for (int i = (int)params_.size(); i <= column; ++i)
|
|
params_.push_back(Param());
|
|
|
|
Param& p = params_[column];
|
|
p.value.resize(value.size());
|
|
if (value.size() > 0)
|
|
memcpy(const_cast<char *>(p.value.data()), &(*value.begin()),
|
|
value.size());
|
|
p.isbinary = true;
|
|
p.isnull = false;
|
|
|
|
// FIXME if first null was bound, check here and invalidate the prepared
|
|
// statement if necessary because the type changes
|
|
}
|
|
|
|
virtual void bindNull(int column)
|
|
{
|
|
DEBUG(std::cerr << this << " bind " << column << " null" << std::endl);
|
|
|
|
for (int i = (int)params_.size(); i <= column; ++i)
|
|
params_.push_back(Param());
|
|
|
|
params_[column].isnull = true;
|
|
}
|
|
|
|
virtual void execute()
|
|
{
|
|
if (conn_.showQueries())
|
|
std::cerr << sql_ << std::endl;
|
|
|
|
// if (!result_)
|
|
// {
|
|
paramValues_ = new char *[params_.size()];
|
|
|
|
for (unsigned i = 0; i < params_.size(); ++i)
|
|
{
|
|
if (params_[i].isbinary)
|
|
{
|
|
paramTypes_ = new int[params_.size() * 3];
|
|
paramLengths_ = paramTypes_ + params_.size();
|
|
paramFormats_ = paramLengths_ + params_.size();
|
|
for (unsigned j = 0; j < params_.size(); ++j)
|
|
{
|
|
paramTypes_[j] = params_[j].isbinary ? BYTEAOID : 0;
|
|
paramFormats_[j] = params_[j].isbinary ? 1 : 0;
|
|
paramLengths_[j] = 0;
|
|
}
|
|
break;
|
|
}
|
|
// }
|
|
|
|
// result_ = PQprepare(conn_.connection(), name_, sql_.c_str(),
|
|
// paramTypes_ ? params_.size() : 0, (Oid *)paramTypes_);
|
|
// handleErr(PQresultStatus(result_));
|
|
}
|
|
|
|
// Transaction tr = conn_.transaction();
|
|
//// if (!this->m_stmt)
|
|
//// {
|
|
// m_stmtnp = conn_.connection()->createStatement(&tr);
|
|
// this->m_stmt = &m_stmtnp;
|
|
//// }
|
|
// //(*this->m_stmt)->TransactionPtr().
|
|
// try
|
|
// {
|
|
// (*this->m_stmt)->Prepare(sql_);
|
|
//// wApp->log("info") << sql_;
|
|
// }
|
|
// catch(IBPP::LogicException &e)
|
|
// {
|
|
// throw FirebirdException(e.what());
|
|
// }
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < params_.size(); ++i)
|
|
{
|
|
if (params_[i].isnull)
|
|
{
|
|
paramValues_[i] = 0;
|
|
(*this->m_stmt)->SetNull(i + 1);
|
|
}
|
|
else
|
|
if (params_[i].isbinary)
|
|
{
|
|
paramValues_[i] = const_cast<char *>(params_[i].value.data());
|
|
paramLengths_[i] = (int) params_[i].value.length();
|
|
(*this->m_stmt)->Set(i + 1, paramValues_[i], paramLengths_[i]);
|
|
}
|
|
else
|
|
{
|
|
paramValues_[i] = const_cast<char *>(params_[i].value.c_str());
|
|
switch((*this->m_stmt)->ParameterType(i + 1))
|
|
{
|
|
case sdString:
|
|
(*this->m_stmt)->Set(i + 1, paramValues_[i]);
|
|
break;
|
|
case sdBlob:
|
|
break;
|
|
|
|
case sdDate:
|
|
break;
|
|
|
|
case sdTime:
|
|
break;
|
|
|
|
case sdTimestamp:
|
|
break;
|
|
|
|
case sdFloat:
|
|
case sdDouble:
|
|
case sdInteger:
|
|
case sdSmallint:
|
|
case sdLargeint:
|
|
Formattable f;
|
|
UErrorCode status = U_ZERO_ERROR;
|
|
f.setDecimalNumber(paramValues_[i], status);
|
|
switch(f.getType())
|
|
{
|
|
case Formattable::kDouble:
|
|
(*this->m_stmt)->Set(i + 1, f.getDouble());
|
|
break;
|
|
case Formattable::kInt64:
|
|
(*this->m_stmt)->Set(i + 1, f.getInt64());
|
|
break;
|
|
case Formattable::kLong:
|
|
long l = f.getLong();
|
|
(*this->m_stmt)->Set(i + 1, l);
|
|
break;
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
try
|
|
{
|
|
|
|
(*this->m_stmt)->Execute();
|
|
// if (sql_.find("select count(1)") == 0)
|
|
// {
|
|
// if ((*this->m_stmt)->Fetch())
|
|
// (*this->m_stmt)->Get(1, affectedRows_);
|
|
// }
|
|
// else
|
|
// {
|
|
affectedRows_ = (*this->m_stmt)->AffectedRows();
|
|
//(*this->m_stmt)->Fetch();
|
|
// }
|
|
|
|
|
|
row_ = 0;
|
|
// if((*this->m_stmt)->Fetch())
|
|
// (*this->m_stmt)->Get(1, lastId_);
|
|
}
|
|
catch(IBPP::LogicException &e)
|
|
{
|
|
throw FirebirdException(e.what());
|
|
}
|
|
// if (PQresultStatus(result_) == PGRES_COMMAND_OK) {
|
|
// std::string s = PQcmdTuples(result_);
|
|
// if (!s.empty())
|
|
// affectedRows_ = boost::lexical_cast<int>(s);
|
|
// else
|
|
// affectedRows_ = 0;
|
|
// } else if (PQresultStatus(result_) == PGRES_TUPLES_OK)
|
|
// affectedRows_ = PQntuples(result_);
|
|
//
|
|
// bool isInsertReturningId = false;
|
|
// if (affectedRows_ == 1) {
|
|
// const std::string returning = " returning ";
|
|
// std::size_t j = sql_.rfind(returning);
|
|
// if (j != std::string::npos
|
|
// && sql_.find(' ', j + returning.length()) == std::string::npos)
|
|
// isInsertReturningId = true;
|
|
// }
|
|
//
|
|
// if (isInsertReturningId) {
|
|
// state_ = NoFirstRow;
|
|
// if (PQntuples(result_) == 1 && PQnfields(result_) == 1) {
|
|
// lastId_ = boost::lexical_cast<long long>(PQgetvalue(result_, 0, 0));
|
|
// }
|
|
// } else {
|
|
// if (PQntuples(result_) == 0) {
|
|
// state_ = NoFirstRow;
|
|
// } else {
|
|
// state_ = FirstRow;
|
|
// }
|
|
// }
|
|
//
|
|
// handleErr(PQresultStatus(result_));
|
|
}
|
|
|
|
virtual long long insertedId()
|
|
{
|
|
return lastId_;
|
|
}
|
|
|
|
virtual int affectedRowCount()
|
|
{
|
|
return affectedRows_;
|
|
}
|
|
|
|
virtual bool nextRow()
|
|
{
|
|
try
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
return (*this->m_stmt)->Fetch();
|
|
}
|
|
catch(IBPP::Exception &e)
|
|
{
|
|
throw FirebirdException(e.what());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool getResult(int column, std::string *value, int size)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
(*this->m_stmt)->Get(column, *value);
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, short *value)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
(*this->m_stmt)->Get(column, *value);
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, int *value)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
(*this->m_stmt)->Get(column, *value);
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, long long *value)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
(*this->m_stmt)->Get(column, *((int64_t *)value));
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, float *value)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
(*this->m_stmt)->Get(column, *value);
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, double *value)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
(*this->m_stmt)->Get(column, *value);
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, boost::posix_time::ptime *value,
|
|
SqlDateTimeType type)
|
|
{
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
return false;
|
|
|
|
switch(type)
|
|
{
|
|
case SqlDate:
|
|
{
|
|
Date d;
|
|
(*this->m_stmt)->Get(column, d);
|
|
*value = boost::posix_time::ptime(boost::gregorian::date(d.Year(), d.Month(), d.Day()));
|
|
break;
|
|
}
|
|
case SqlDateTime:
|
|
{
|
|
Timestamp tm;
|
|
(*this->m_stmt)->Get(column, tm);
|
|
*value = boost::posix_time::ptime(boost::gregorian::date(tm.Year(), tm.Month(), tm.Day()), boost::posix_time::hours(tm.Hours()) + boost::posix_time::minutes(tm.Minutes()) + boost::posix_time::seconds(tm.Seconds()) + boost::posix_time::microseconds(tm.SubSeconds() * 100));
|
|
break;
|
|
}
|
|
case SqlTime:
|
|
{
|
|
Time t;
|
|
(*this->m_stmt)->Get(column, t);
|
|
*value = boost::posix_time::ptime(boost::gregorian::date(0, 0, 0), boost::posix_time::hours(t.Hours()) + boost::posix_time::minutes(t.Minutes()) + boost::posix_time::seconds(t.Seconds()) + boost::posix_time::microseconds(t.SubSeconds() * 100));
|
|
}
|
|
}
|
|
//value->resize(size);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, boost::posix_time::time_duration *value)
|
|
{
|
|
// if (!this->m_stmt)
|
|
// {
|
|
// if ((*this->m_stmt)->IsNull(column))
|
|
// return false;
|
|
//
|
|
// switch(type)
|
|
// {
|
|
// case SqlDate:
|
|
// Date d;
|
|
// (*this->m_stmt)->Get(column, d);
|
|
// *value = boost::posix_time::ptime(boost::gregorian::date(d.Year(), d.Month(), d.Day()));
|
|
// break;
|
|
// case SqlDateTime:
|
|
// Timestamp tm;
|
|
// (*this->m_stmt)->Get(column, tm);
|
|
// *value = boost::posix_time::ptime(boost::gregorian::date(tm.Year(), tm.Month(), tm.Day()), boost::posix_time::hours(tm.Hours()) + boost::posix_time::minutes(tm.Minutes()) + boost::posix_time::seconds(tm.Seconds()) + boost::posix_time::microseconds(tm.SubSeconds() * 100));
|
|
// break;
|
|
// case SqlTime:
|
|
// Time t;
|
|
// (*this->m_stmt)->Get(column, t);
|
|
// *value = boost::posix_time::ptime(boost::gregorian::date(0, 0, 0), boost::posix_time::hours(t.Hours()) + boost::posix_time::minutes(t.Minutes()) + boost::posix_time::seconds(t.Seconds()) + boost::posix_time::microseconds(t.SubSeconds() * 100));
|
|
// }
|
|
// //value->resize(size);
|
|
// }
|
|
// else
|
|
return false;
|
|
|
|
// DEBUG(std::cerr << this
|
|
// << " result string " << column << " " << *value << std::endl);
|
|
|
|
// return true;
|
|
}
|
|
|
|
virtual bool getResult(int column, std::vector<unsigned char> *value,
|
|
int size)
|
|
{
|
|
char *result = new char[size];
|
|
if (this->m_stmt && this->m_stmt->intf())
|
|
{
|
|
if ((*this->m_stmt)->IsNull(++column))
|
|
{
|
|
delete[] result;
|
|
return false;
|
|
}
|
|
|
|
(*this->m_stmt)->Get(column, result, size);
|
|
//value->resize(size);
|
|
|
|
for(int i = 0; i < size; i++)
|
|
{
|
|
value->push_back(result[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete[] result;
|
|
return false;
|
|
}
|
|
DEBUG(std::cerr << this
|
|
<< " result string " << column << " " << *value << std::endl);
|
|
|
|
delete[] result;
|
|
return true;
|
|
}
|
|
|
|
virtual std::string sql() const {
|
|
return sql_;
|
|
}
|
|
|
|
private:
|
|
struct Param {
|
|
std::string value;
|
|
bool isnull, isbinary;
|
|
|
|
Param() : isnull(true), isbinary(false) { }
|
|
};
|
|
|
|
Firebird& conn_;
|
|
std::string sql_;
|
|
IBPP::Statement *m_stmt;
|
|
IBPP::Statement m_stmtnp;
|
|
char name_[64];
|
|
//PGresult *result_;
|
|
enum { NoFirstRow, FirstRow, NextRow, Done } state_;
|
|
std::vector<Param> params_;
|
|
|
|
char **paramValues_;
|
|
int *paramTypes_, *paramLengths_, *paramFormats_;
|
|
|
|
int lastId_, row_, affectedRows_;
|
|
|
|
// void handleErr(int err)
|
|
// {
|
|
// if (err != PGRES_COMMAND_OK && err != PGRES_TUPLES_OK)
|
|
// throw PostgresException(PQerrorMessage(conn_.connection()));
|
|
// }
|
|
|
|
void setValue(int column, const std::string& value)
|
|
{
|
|
for (int i = (int)params_.size(); i <= column; ++i)
|
|
params_.push_back(Param());
|
|
|
|
params_[column].value = value;
|
|
params_[column].isnull = false;
|
|
}
|
|
|
|
std::string convertToNumberedPlaceholders(const std::string& sql)
|
|
{
|
|
// std::stringstream result;
|
|
//
|
|
// enum { Statement, SQuote, DQuote } state = Statement;
|
|
// int placeholder = 1;
|
|
//
|
|
// for (unsigned i = 0; i < sql.length(); ++i) {
|
|
// switch (state) {
|
|
// case Statement:
|
|
// if (sql[i] == '\'')
|
|
// state = SQuote;
|
|
// else if (sql[i] == '"')
|
|
// state = DQuote;
|
|
// else if (sql[i] == '?') {
|
|
// result << '$' << placeholder++;
|
|
// continue;
|
|
// }
|
|
// break;
|
|
// case SQuote:
|
|
// if (sql[i] == '\'') {
|
|
// if (i + 1 == sql.length())
|
|
// state = Statement;
|
|
// else if (sql[i + 1] == '\'') {
|
|
// result << sql[i];
|
|
// ++i; // skip to next
|
|
// } else
|
|
// state = Statement;
|
|
// }
|
|
// break;
|
|
// case DQuote:
|
|
// if (sql[i] == '"')
|
|
// state = Statement;
|
|
// break;
|
|
// }
|
|
// result << sql[i];
|
|
// }
|
|
//
|
|
// return result.str();
|
|
return sql;
|
|
}
|
|
};
|
|
|
|
Firebird::Firebird()
|
|
: m_tr(NULL), m_writableTransaction(false), m_dmOwned(true)
|
|
{
|
|
this->m_dm = new DatabaseModule();
|
|
}
|
|
|
|
Firebird::Firebird(DatabaseModule *dm)
|
|
: m_dm(dm), m_tr(NULL), m_writableTransaction(false), m_dmOwned(false)
|
|
{
|
|
// if (!db.empty())
|
|
// connect(db);
|
|
}
|
|
|
|
Firebird::Firebird(const Firebird& other)
|
|
: SqlConnection(other), m_dm(other.m_dm), m_tr(other.m_tr)
|
|
, m_writableTransaction(other.m_writableTransaction), m_dmOwned(false)
|
|
{
|
|
// if (!other.connInfo_.empty())
|
|
// this->connect(other.connInfo_);
|
|
}
|
|
|
|
Firebird::~Firebird()
|
|
{
|
|
clearStatementCache();
|
|
// if (conn_)
|
|
// PQfinish(conn_);
|
|
if (this->m_dmOwned)
|
|
if (this->m_dm)
|
|
delete this->m_dm;
|
|
}
|
|
|
|
Firebird *Firebird::clone() const
|
|
{
|
|
return new Firebird(*this);
|
|
}
|
|
|
|
bool Firebird::connect(const std::string& db)
|
|
{
|
|
if (!this->m_dm)
|
|
return false;
|
|
|
|
// connInfo_ = db;
|
|
// conn_ = PQconnectdb(db.c_str());
|
|
//
|
|
// if (PQstatus(conn_) != CONNECTION_OK) {
|
|
// std::string error = PQerrorMessage(conn_);
|
|
// PQfinish(conn_);
|
|
// conn_ = 0;
|
|
// throw PostgresException("Could not connect to: " + error);
|
|
// }
|
|
//
|
|
// PQsetClientEncoding(conn_, "UTF8");
|
|
|
|
this->m_dm->connect(this->m_dm->getServerName(), db,
|
|
this->m_dm->getUserName(), this->m_dm->getUserPassword(),
|
|
this->m_dm->getRoleName(), this->m_dm->getCharset(),
|
|
this->m_dm->getCreateParams());
|
|
return true;
|
|
}
|
|
|
|
SqlStatement *Firebird::prepareStatement(const std::string& sql)
|
|
{
|
|
return new FirebirdStatement(*this, sql);
|
|
}
|
|
|
|
void Firebird::executeSql(const std::string &sql)
|
|
{
|
|
|
|
if (showQueries())
|
|
std::cerr << sql << std::endl;
|
|
SqlStatement *stmt = 0;
|
|
|
|
try
|
|
{
|
|
this->startTransaction();
|
|
stmt = this->prepareStatement(sql);
|
|
|
|
stmt->execute();
|
|
|
|
this->commitTransaction();
|
|
}
|
|
catch(...)
|
|
{
|
|
if (this->m_tr)
|
|
if ((*this->m_tr)->Started())
|
|
(*this->m_tr)->Rollback();
|
|
}
|
|
if (stmt)
|
|
delete stmt;
|
|
|
|
// result = PQexec(conn_, sql.c_str());
|
|
// err = PQresultStatus(result);
|
|
// if (err != PGRES_COMMAND_OK && err != PGRES_TUPLES_OK) {
|
|
// PQclear(result);
|
|
// throw PostgresException(PQerrorMessage(conn_));
|
|
// }
|
|
// PQclear(result);
|
|
}
|
|
|
|
std::string Firebird::autoincrementType() const
|
|
{
|
|
//return "serial";
|
|
return std::string();
|
|
}
|
|
|
|
std::string Firebird::autoincrementSql() const
|
|
{
|
|
return std::string();
|
|
}
|
|
|
|
std::string Firebird::autoincrementInsertSuffix() const
|
|
{
|
|
return std::string();
|
|
}
|
|
|
|
const char *Firebird::dateTimeType(SqlDateTimeType type) const
|
|
{
|
|
switch (type) {
|
|
case SqlDate:
|
|
return "date";
|
|
case SqlDateTime:
|
|
return "timestamp";
|
|
case SqlTime:
|
|
return "time";
|
|
}
|
|
|
|
std::stringstream ss;
|
|
ss << __FILE__ << ":" << __LINE__ << ": implementation error";
|
|
throw FirebirdException(ss.str());
|
|
}
|
|
|
|
const char *Firebird::blobType() const
|
|
{
|
|
return "blob not null";
|
|
}
|
|
|
|
void Firebird::startTransaction()
|
|
{
|
|
// if (this->m_tr)
|
|
// delete this->m_tr;
|
|
if (!this->m_tr)
|
|
{
|
|
if (this->m_writableTransaction)
|
|
{
|
|
m_tra = this->m_dm->createTransaction(amWrite, ilReadCommitted, lrWait);
|
|
this->m_tr = &m_tra;
|
|
}
|
|
else
|
|
{
|
|
m_tra = this->m_dm->createTransaction(amRead, ilReadCommitted, lrWait);
|
|
this->m_tr = &m_tra;
|
|
}
|
|
}
|
|
(*this->m_tr)->Start();
|
|
}
|
|
|
|
void Firebird::commitTransaction()
|
|
{
|
|
if (this->m_tr && this->m_tr->intf())
|
|
(*this->m_tr)->Commit();
|
|
}
|
|
|
|
void Firebird::rollbackTransaction()
|
|
{
|
|
if (this->m_tr && this->m_tr->intf())
|
|
(*this->m_tr)->Rollback();
|
|
}
|
|
|
|
}
|
|
}
|
|
|