diff --git a/bazaar/Firebird/Firebird.cpp b/bazaar/Firebird/Firebird.cpp new file mode 100644 index 000000000..56a038d38 --- /dev/null +++ b/bazaar/Firebird/Firebird.cpp @@ -0,0 +1,1877 @@ +#include "Firebird.h" +#include + +NAMESPACE_UPP + +TransAuto::TransAuto(SqlSession& s) : abort(true), isSession(true), session(&s) +{ + session->Begin(); +} + +TransAuto::TransAuto(Sql& s) : abort(true), isSession(false), sql(&s) +{ + sql->Begin(); +} + +TransAuto::~TransAuto() +{ + try { + if (isSession) + { + if(abort) { + session->Rollback(); + } else { + session->Commit(); + } + } else { + if(abort) { + sql->Rollback(); + } else { + sql->Commit(); + } + } + } catch(...) { + // Ignore all exceptions in destructor. + ASSERT(false); + } +} + +class TransRetain +{ +public: + TransRetain(FBSession& s) : abort(true), session(&s) + { + } + ~TransRetain() + { + try { + if(abort) { + session->RollbackRetaining(); + } else { + session->CommitRetaining(); + } + } catch(...) { + // Ignore all exceptions in the destructor. + ASSERT(false); + } + } + +public: + operator bool() const { return abort; } + void Finish() { abort = false; } + +protected: + bool abort:1; + FBSession* session; +}; + +#define TRANSACTION_RETAIN(trans) \ +for(TransRetain auto_trans_##__LINE__(trans); \ + auto_trans_##__LINE__; \ + auto_trans_##__LINE__.Finish() ) + +struct FBValue { + short nullInd; + XSQLVAR* pXSQLVar; + + FBValue(XSQLVAR& v); + virtual ~FBValue(); + + bool CanBeNull() const { return pXSQLVar->sqltype & 1; } + bool IsNull() const { return nullInd == -1; } + void SetNull(bool flag = true) { nullInd = flag ? -1 : 0; } + + virtual void GetValue(Ref r) const = 0; + virtual void SetValue(const Value& v) = 0; +}; + +FBValue::FBValue(XSQLVAR& v) +{ + pXSQLVar = &v; + if (CanBeNull()) + { + v.sqlind = &nullInd; + nullInd = -1; + } +} + +FBValue::~FBValue() +{ +} + +struct FBInt : public FBValue { + int value; + + FBInt(XSQLVAR& v); + + virtual void GetValue(Ref r) const; + virtual void SetValue(const Value& v); +}; + +FBInt::FBInt(XSQLVAR& v) : FBValue(v) +{ + v.sqltype = SQL_LONG + (v.sqltype & 1); + v.sqldata = reinterpret_cast(&value); + v.sqllen = sizeof(value); +} + +void FBInt::GetValue(Ref r) const +{ + if (IsNull()) + r = Null; + else { + switch(r.GetType()) + { + case INT_V: + RefInt(r) = value; + break; + case DOUBLE_V: + RefDouble(r) = static_cast(value); + break; + case STRING_V: + RefString(r) = FormatInt(value); + break; + case VALUE_V: + RefValue(r) = Value(value); + break; + case WSTRING_V: + RefWString(r) = FormatInt(value).ToWString(); + break; + case INT64_V: + RefInt64(r) = value; + break; + case BOOL_V: + RefBool(r) = value != 0; + break; + case DATE_V: + case TIME_V: + default: + ASSERT(false); + break; + } + } +} + +void FBInt::SetValue(const Value& v) +{ + SetNull(v.IsNull()); + + if (v.IsNull()) + return; + + switch (v.GetType()) + { + case INT_V: + value = ValueTo(v); + break; + case DOUBLE_V: + value = static_cast(ValueTo(v)); + break; + case STRING_V: + value = ScanInt(ValueTo(v)); + break; +// case DATE_V: +// case TIME_V: + case VALUE_V: + SetValue(ValueTo(v)); + break; + case WSTRING_V: + value = ScanInt(ValueTo(v).ToString()); + break; + case INT64_V: + value = static_cast(ValueTo(v)); + break; + case BOOL_V: + value = ValueTo(v) ? 1 : 0; + break; + default: + ASSERT(false); + break; + } +} + +struct FBInt64 : public FBValue { + int64 value; + + FBInt64(XSQLVAR& v); + + virtual void GetValue(Ref r) const; + virtual void SetValue(const Value& v); +}; + +FBInt64::FBInt64(XSQLVAR& v) : FBValue(v) +{ + v.sqltype = SQL_INT64 + (v.sqltype & 1); + v.sqldata = reinterpret_cast(&value); + v.sqllen = sizeof(value); +} + +void FBInt64::GetValue(Ref r) const +{ + if (IsNull()) + r = Null; + else { + switch(r.GetType()) + { + case INT_V: + RefInt(r) = static_cast(value); + break; + case DOUBLE_V: + RefDouble(r) = static_cast(value); + break; + case STRING_V: + RefString(r) = FormatInt64(value); + break; + case VALUE_V: + RefValue(r) = Value(value); + break; + case WSTRING_V: + RefWString(r) = FormatInt64(value).ToWString(); + break; + case INT64_V: + RefInt64(r) = value; + break; + case BOOL_V: + RefBool(r) = value != 0; + break; + case DATE_V: + case TIME_V: + default: + ASSERT(false); + break; + } + } +} + +void FBInt64::SetValue(const Value& v) +{ + SetNull(v.IsNull()); + + if (v.IsNull()) + return; + + switch (v.GetType()) + { + case INT_V: + value = ValueTo(v); + break; + case DOUBLE_V: + value = static_cast(ValueTo(v)); + break; + case STRING_V: + value = ScanInt64(ValueTo(v)); + break; +// case DATE_V: +// case TIME_V: + case VALUE_V: + SetValue(ValueTo(v)); + break; + case WSTRING_V: + value = ScanInt64(ValueTo(v).ToString()); + break; + case INT64_V: + value = ValueTo(v); + break; + case BOOL_V: + value = ValueTo(v) ? 1 : 0; + break; + default: + ASSERT(false); + break; + } +} + +struct FBDouble : public FBValue { + double value; + + FBDouble(XSQLVAR& v); + + virtual void GetValue(Ref r) const; + virtual void SetValue(const Value& v); +}; + +FBDouble::FBDouble(XSQLVAR& v) : FBValue(v) +{ + v.sqltype = SQL_DOUBLE + (v.sqltype & 1); + v.sqldata = reinterpret_cast(&value); + v.sqllen = sizeof(value); + v.sqlscale = 18; +} + +void FBDouble::GetValue(Ref r) const +{ + if (IsNull()) + r = Null; + else { + switch(r.GetType()) + { + case INT_V: + RefInt(r) = static_cast(value); + break; + case DOUBLE_V: + RefDouble(r) = value; + break; + case STRING_V: + RefString(r) = FormatDouble(value); + break; + case VALUE_V: + RefValue(r) = Value(value); + break; + case WSTRING_V: + RefWString(r) = FormatDouble(value).ToWString(); + break; + case INT64_V: + RefInt64(r) = static_cast(value); + break; + case BOOL_V: + RefBool(r) = value != 0.0; + break; + case DATE_V: + case TIME_V: + default: + ASSERT(false); + break; + } + } +} + +void FBDouble::SetValue(const Value& v) +{ + SetNull(v.IsNull()); + + if (v.IsNull()) + return; + + switch (v.GetType()) + { + case INT_V: + value = ValueTo(v); + break; + case DOUBLE_V: + value = ValueTo(v); + break; + case STRING_V: + value = ScanDouble(ValueTo(v)); + break; +// case DATE_V: +// case TIME_V: + case VALUE_V: + SetValue(ValueTo(v)); + break; + case WSTRING_V: + value = ScanDouble(ValueTo(v).ToString()); + break; + case INT64_V: + value = static_cast(ValueTo(v)); + break; + case BOOL_V: + value = ValueTo(v) ? 1.0 : 0.0; + break; + default: + ASSERT(false); + break; + } +} + +// This macro is used to declare structures representing SQL VARCHAR types +#define SQL_VARCHAR(len) struct {short vary_length; char vary_string[(len) + 1];} + +struct FBVarying : public FBValue { +// enum { max_varchar_size = 8 * 1024 }; + enum { max_varchar_size = 32765 }; + + //String value; + SQL_VARCHAR(32765) buff; + + FBVarying(XSQLVAR& v); + + void SetValue(const String& str); + + virtual void GetValue(Ref r) const; + virtual void SetValue(const Value& v); +}; + +FBVarying::FBVarying(XSQLVAR& v) : FBValue(v) +{ + v.sqltype = SQL_VARYING + (v.sqltype & 1); + v.sqldata = reinterpret_cast(&buff); + v.sqllen = v.sqllen == 0 ? max_varchar_size : v.sqllen; +} + +void FBVarying::SetValue(const String& str) +{ + ASSERT(pXSQLVar); + buff.vary_length = min(str.GetCount(), pXSQLVar->sqllen); + strncpy(buff.vary_string, ~str, buff.vary_length); +} + +void FBVarying::GetValue(Ref r) const +{ + if (IsNull()) + r = Null; + else { + switch(r.GetType()) { + case INT_V: + { + const char* e = buff.vary_string + buff.vary_length; + RefInt(r) = ScanInt(buff.vary_string, &e); + } + break; + case DOUBLE_V: + { + const char* e = buff.vary_string + buff.vary_length; + RefDouble(r) = ScanDouble(buff.vary_string, &e); + } + break; + case STRING_V: + RefString(r) = String(buff.vary_string, buff.vary_length); + break; + case DATE_V: + r.SetValue(UPP::Scan(DATE_V, String(buff.vary_string, buff.vary_length))); + break; + case TIME_V: + r.SetValue(UPP::Scan(TIME_V, String(buff.vary_string, buff.vary_length))); + break; + case VALUE_V: + RefValue(r) = Value(String(buff.vary_string, buff.vary_length)); + break; + case WSTRING_V: + RefWString(r) = WString(buff.vary_string, buff.vary_length); + break; + case INT64_V: + { + const char* e = buff.vary_string + buff.vary_length; + RefInt64(r) = ScanInt64(buff.vary_string, &e); + } + break; + case BOOL_V: + { + const char* e = buff.vary_string + buff.vary_length; + RefBool(r) = ScanInt(buff.vary_string, &e) != 0; + } + break; + default: + ASSERT(false); + break; + } + } +} + +void FBVarying::SetValue(const Value& v) +{ + SetNull(v.IsNull()); + + if (v.IsNull()) + return; + + switch (v.GetType()) + { + case INT_V: + SetValue(AsString(ValueTo(v))); + break; + case DOUBLE_V: + SetValue(AsString(ValueTo(v))); + break; + case STRING_V: + SetValue(ValueTo(v)); + break; +// case DATE_V: +// case TIME_V: + case VALUE_V: + SetValue(ValueTo(v)); + break; + case WSTRING_V: + SetValue(ValueTo(v).ToString()); + break; + case INT64_V: + SetValue(AsString(ValueTo(v))); + break; + case BOOL_V: + SetValue(IntStr((int)ValueTo(v))); + break; + default: + ASSERT(false); + break; + } +} + +struct FBTimeStamp : public FBValue { + ISC_TIMESTAMP value; + + FBTimeStamp(XSQLVAR& v); + + virtual void GetValue(Ref r) const; + virtual void SetValue(const Value& v); +}; + +FBTimeStamp::FBTimeStamp(XSQLVAR& v) : FBValue(v) +{ + v.sqltype = SQL_TIMESTAMP + (v.sqltype & 1); + v.sqldata = reinterpret_cast(&value); + v.sqllen = sizeof(value); +} + +void FBTimeStamp::GetValue(Ref r) const +{ + if (IsNull()) + r = Null; + else { + const LanguageInfo& li = GetLanguageInfo(); + struct tm time; + isc_decode_timestamp(&value, &time); + + const Time t(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday, + time.tm_hour, time.tm_min, time.tm_sec); + + switch(r.GetType()) { + case STRING_V: + RefString(r) = li.FormatTime(t); + break; + case DATE_V: + RefDate(r) = t; + break; + case TIME_V: + RefTime(r) = t; + break; + case VALUE_V: + RefValue(r) = t; + break; + case WSTRING_V: + RefWString(r) = li.FormatTime(t).ToWString(); + break; + case INT64_V: + RefInt64(r) = t.Get(); + break; + case DOUBLE_V: + RefDouble(r) = static_cast(t.Get()); + break; + case INT_V: + case BOOL_V: + default: + ASSERT(false); + break; + } + } +} + +void FBTimeStamp::SetValue(const Value& v) +{ + SetNull(v.IsNull()); + + if (v.IsNull()) + return; + + Time t; + switch (v.GetType()) + { + case INT_V: + t.Set(ValueTo(v)); + break; + case DOUBLE_V: + t.Set((int64)ValueTo(v)); + case STRING_V: + t = UPP::Scan(TIME_V, ValueTo(v)); + break; + case DATE_V: + { + const Date& d = ValueTo(v); + t = Time(d.year, d.month, d.day); + } + break; + case TIME_V: + t = ValueTo