+++ /dev/null
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// File : $Id: row.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $\r
-// Subject : IBPP, Row class implementation\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)\r
-//\r
-// The contents of this file are subject to the IBPP License (the "License");\r
-// you may not use this file except in compliance with the License. You may\r
-// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'\r
-// file which must have been distributed along with this file.\r
-//\r
-// This software, distributed under the License, is distributed on an "AS IS"\r
-// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the\r
-// License for the specific language governing rights and limitations\r
-// under the License.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-//\r
-// COMMENTS\r
-// * Tabulations should be set every four characters when editing this file.\r
-//\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-#ifdef _MSC_VER\r
-#pragma warning(disable: 4786 4996)\r
-#ifndef _DEBUG\r
-#pragma warning(disable: 4702)\r
-#endif\r
-#endif\r
-\r
-#include "_ibpp.h"\r
-\r
-#ifdef HAS_HDRSTOP\r
-#pragma hdrstop\r
-#endif\r
-\r
-#include <math.h>\r
-#include <time.h>\r
-#include <cstring>\r
-\r
-using namespace ibpp_internals;\r
-\r
-// (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))\r
-\r
-void RowImpl::SetNull(int param)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::SetNull", _("The row is not initialized."));\r
- if (param < 1 || param > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::SetNull", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[param-1]);\r
- if (! (var->sqltype & 1))\r
- throw LogicExceptionImpl("Row::SetNull", _("This column can't be null."));\r
-\r
- *var->sqlind = -1; // Set the column to SQL NULL\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, bool value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[bool]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivBool, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const char* cstring)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[char*]", _("The row is not initialized."));\r
- if (cstring == 0)\r
- throw LogicExceptionImpl("Row::Set[char*]", _("null char* pointer detected."));\r
-\r
- SetValue(param, ivByte, cstring, (int)strlen(cstring));\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const void* bindata, int len)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[void*]", _("The row is not initialized."));\r
- if (bindata == 0)\r
- throw LogicExceptionImpl("Row::Set[void*]", _("null char* pointer detected."));\r
- if (len < 0)\r
- throw LogicExceptionImpl("Row::Set[void*]", _("Length must be >= 0"));\r
- \r
- SetValue(param, ivByte, bindata, len);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const std::string& s)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[string]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivString, (void*)&s);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, int16_t value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[int16_t]", _("The row is not initialized."));\r
- \r
- SetValue(param, ivInt16, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, int32_t value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[int32_t]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivInt32, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, int64_t value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[int64_t]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivInt64, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, float value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[float]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivFloat, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, double value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[double]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivDouble, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Timestamp& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Timestamp]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivTimestamp, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Date& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Date]", _("The row is not initialized."));\r
-\r
- if (mDialect == 1)\r
- {\r
- // In dialect 1, IBPP::Date is supposed to work with old 'DATE'\r
- // fields which are actually ISC_TIMESTAMP.\r
- IBPP::Timestamp timestamp(value);\r
- SetValue(param, ivTimestamp, ×tamp);\r
- }\r
- else\r
- {\r
- // Dialect 3\r
- SetValue(param, ivDate, (void*)&value);\r
- }\r
-\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Time& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Time]", _("The row is not initialized."));\r
- if (mDialect == 1)\r
- throw LogicExceptionImpl("Row::Set[Time]", _("Requires use of a dialect 3 database."));\r
-\r
- SetValue(param, ivTime, &value);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Blob& blob)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Blob]", _("The row is not initialized."));\r
- if (mDatabase != 0 && blob->DatabasePtr() != mDatabase)\r
- throw LogicExceptionImpl("Row::Set[Blob]",\r
- _("IBlob and Row attached to different databases"));\r
- if (mTransaction != 0 && blob->TransactionPtr() != mTransaction)\r
- throw LogicExceptionImpl("Row::Set[Blob]",\r
- _("IBlob and Row attached to different transactions"));\r
-\r
- SetValue(param, ivBlob, blob.intf());\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::Array& array)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Array]", _("The row is not initialized."));\r
- if (mDatabase != 0 && array->DatabasePtr() != mDatabase)\r
- throw LogicExceptionImpl("Row::Set[Array]",\r
- _("IArray and Row attached to different databases"));\r
- if (mTransaction != 0 && array->TransactionPtr() != mTransaction)\r
- throw LogicExceptionImpl("Row::Set[Array]",\r
- _("IArray and Row attached to different transactions"));\r
-\r
- SetValue(param, ivArray, (void*)array.intf());\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-void RowImpl::Set(int param, const IBPP::DBKey& key)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[DBKey]", _("The row is not initialized."));\r
-\r
- SetValue(param, ivDBKey, (void*)&key);\r
- mUpdated[param-1] = true;\r
-}\r
-\r
-/*\r
-void RowImpl::Set(int param, const IBPP::Value& value)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Set[Value]", _("The row is not initialized."));\r
-\r
- //SetValue(param, ivDBKey, (void*)&key);\r
- //mUpdated[param-1] = true;\r
-}\r
-*/\r
-\r
-bool RowImpl::IsNull(int column)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
- if (column < 1 || column > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::IsNull", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[column-1]);\r
- return ((var->sqltype & 1) && *(var->sqlind) != 0) ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, bool& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivBool);\r
- if (pvalue != 0)\r
- retvalue = (*(char*)pvalue == 0 ? false : true);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, char* retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
- if (retvalue == 0)\r
- throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
-\r
- int sqllen;\r
- void* pvalue = GetValue(column, ivByte, &sqllen);\r
- if (pvalue != 0)\r
- {\r
- memcpy(retvalue, pvalue, sqllen);\r
- retvalue[sqllen] = '\0';\r
- }\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, void* bindata, int& userlen)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
- if (bindata == 0)\r
- throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));\r
- if (userlen < 0)\r
- throw LogicExceptionImpl("Row::Get", _("Length must be >= 0"));\r
-\r
- int sqllen;\r
- void* pvalue = GetValue(column, ivByte, &sqllen);\r
- if (pvalue != 0)\r
- {\r
- // userlen says how much bytes the user can accept\r
- // let's shorten it, if there is less bytes available\r
- if (sqllen < userlen) userlen = sqllen;\r
- memcpy(bindata, pvalue, userlen);\r
- }\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, std::string& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivString, &retvalue);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, int16_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivInt16);\r
- if (pvalue != 0)\r
- retvalue = *(int16_t*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, int32_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivInt32);\r
- if (pvalue != 0)\r
- retvalue = *(int32_t*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, int64_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivInt64);\r
- if (pvalue != 0)\r
- retvalue = *(int64_t*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, float& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivFloat);\r
- if (pvalue != 0)\r
- retvalue = *(float*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, double& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivDouble);\r
- if (pvalue != 0)\r
- retvalue = *(double*)pvalue;\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Timestamp& timestamp)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Date& date)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- if (mDialect == 1)\r
- {\r
- // Dialect 1. IBPP::Date is supposed to work with old 'DATE'\r
- // fields which are actually ISC_TIMESTAMP.\r
- IBPP::Timestamp timestamp;\r
- void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);\r
- if (pvalue != 0) date = timestamp;\r
- return pvalue == 0 ? true : false;\r
- }\r
- else\r
- {\r
- void* pvalue = GetValue(column, ivDate, (void*)&date);\r
- return pvalue == 0 ? true : false;\r
- }\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Time& time)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivTime, (void*)&time);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Blob& retblob)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivBlob, (void*)retblob.intf());\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::DBKey& retkey)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivDBKey, (void*)&retkey);\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-bool RowImpl::Get(int column, IBPP::Array& retarray)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- void* pvalue = GetValue(column, ivArray, (void*)retarray.intf());\r
- return pvalue == 0 ? true : false;\r
-}\r
-\r
-/*\r
-const IBPP::Value RowImpl::Get(int column)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- //void* value = GetValue(column, ivArray, (void*)retarray.intf());\r
- //return value == 0 ? true : false;\r
- return IBPP::Value();\r
-}\r
-*/\r
-\r
-bool RowImpl::IsNull(const std::string& name)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));\r
-\r
- return IsNull(ColumnNum(name));\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, bool& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, char* retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get[char*]", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, void* retvalue, int& count)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get[void*,int]", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue, count);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, std::string& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::GetString", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, int16_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, int32_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, int64_t& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, float& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, double& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Date& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Time& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string&name, IBPP::Blob& retblob)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retblob);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::DBKey& retvalue)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retvalue);\r
-}\r
-\r
-bool RowImpl::Get(const std::string& name, IBPP::Array& retarray)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name), retarray);\r
-}\r
-\r
-/*\r
-const IBPP::Value RowImpl::Get(const std::string& name)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));\r
-\r
- return Get(ColumnNum(name));\r
-}\r
-*/\r
-\r
-int RowImpl::Columns()\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::Columns", _("The row is not initialized."));\r
-\r
- return mDescrArea->sqld;\r
-}\r
-\r
-int RowImpl::ColumnNum(const std::string& name)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnNum", _("The row is not initialized."));\r
- if (name.empty())\r
- throw LogicExceptionImpl("Row::ColumnNum", _("Column name <empty> not found."));\r
-\r
- XSQLVAR* var;\r
- char Uname[sizeof(var->sqlname)+1]; // Max size of sqlname + '\0'\r
-\r
- // Local upper case copy of the column name\r
- size_t len = name.length();\r
- if (len > sizeof(var->sqlname)) len = sizeof(var->sqlname);\r
- strncpy(Uname, name.c_str(), len);\r
- Uname[len] = '\0';\r
- char* p = Uname;\r
- while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
-\r
- // Loop through the columns of the descriptor\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- var = &(mDescrArea->sqlvar[i]);\r
- if (var->sqlname_length != (int16_t)len) continue;\r
- if (strncmp(Uname, var->sqlname, len) == 0) return i+1;\r
- }\r
-\r
- // Failed finding the column name, let's retry using the aliases\r
- char Ualias[sizeof(var->aliasname)+1]; // Max size of aliasname + '\0'\r
-\r
- // Local upper case copy of the column name\r
- len = name.length();\r
- if (len > sizeof(var->aliasname)) len = sizeof(var->aliasname);\r
- strncpy(Ualias, name.c_str(), len);\r
- Ualias[len] = '\0';\r
- p = Ualias;\r
- while (*p != '\0') { *p = char(toupper(*p)); ++p; }\r
-\r
- // Loop through the columns of the descriptor\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- var = &(mDescrArea->sqlvar[i]);\r
- if (var->aliasname_length != (int16_t)len) continue;\r
- if (strncmp(Ualias, var->aliasname, len) == 0) return i+1;\r
- }\r
-\r
- throw LogicExceptionImpl("Row::ColumnNum", _("Could not find matching column."));\r
-#ifdef __DMC__\r
- return 0; // DMC errronously warns here about a missing return\r
-#endif\r
-}\r
-\r
-/*\r
-ColumnName, ColumnAlias, ColumnTable : all these 3 have a mistake.\r
-Ideally, the strings should be stored elsewhere (like _Numerics and so on) to\r
-take into account the final '\0' which needs to be added. For now, we insert\r
-the '\0' in the original data, which will cut the 32th character. Not terribly\r
-bad, but should be cleanly rewritten.\r
-*/\r
-\r
-const char* RowImpl::ColumnName(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnName", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumName", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- if (var->sqlname_length >= 31) var->sqlname_length = 31;\r
- var->sqlname[var->sqlname_length] = '\0';\r
- return var->sqlname;\r
-}\r
-\r
-const char* RowImpl::ColumnAlias(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnAlias", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnAlias", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- if (var->aliasname_length >= 31) var->aliasname_length = 31;\r
- var->aliasname[var->aliasname_length] = '\0';\r
- return var->aliasname;\r
-}\r
-\r
-const char* RowImpl::ColumnTable(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnTable", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnTable", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- if (var->relname_length >= 31) var->relname_length = 31;\r
- var->relname[var->relname_length] = '\0';\r
- return var->relname;\r
-}\r
-\r
-IBPP::SDT RowImpl::ColumnType(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnType", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnType", _("Variable index out of range."));\r
-\r
- IBPP::SDT value;\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
-\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_TEXT : value = IBPP::sdString; break;\r
- case SQL_VARYING : value = IBPP::sdString; break;\r
- case SQL_SHORT : value = IBPP::sdSmallint; break;\r
- case SQL_LONG : value = IBPP::sdInteger; break;\r
- case SQL_INT64 : value = IBPP::sdLargeint; break;\r
- case SQL_FLOAT : value = IBPP::sdFloat; break;\r
- case SQL_DOUBLE : value = IBPP::sdDouble; break;\r
- case SQL_TIMESTAMP : value = IBPP::sdTimestamp; break;\r
- case SQL_TYPE_DATE : value = IBPP::sdDate; break;\r
- case SQL_TYPE_TIME : value = IBPP::sdTime; break;\r
- case SQL_BLOB : value = IBPP::sdBlob; break;\r
- case SQL_ARRAY : value = IBPP::sdArray; break;\r
- default : throw LogicExceptionImpl("Row::ColumnType",\r
- _("Found an unknown sqltype !"));\r
- }\r
-\r
- return value;\r
-}\r
-\r
-int RowImpl::ColumnSubtype(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnSubtype", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnSubtype", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- return (int)var->sqlsubtype;\r
-}\r
-\r
-int RowImpl::ColumnSize(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnSize", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnSize", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- return var->sqllen;\r
-}\r
-\r
-int RowImpl::ColumnScale(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnScale", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnScale", _("Variable index out of range."));\r
-\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- return -var->sqlscale;\r
-}\r
-\r
-bool RowImpl::ColumnUpdated(int varnum)\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("Row::ColumnUpdated", _("Variable index out of range."));\r
-\r
- return mUpdated[varnum-1];\r
-}\r
-\r
-bool RowImpl::Updated()\r
-{\r
- if (mDescrArea == 0)\r
- throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));\r
-\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- if (mUpdated[i]) return true;\r
- return false;\r
-}\r
-\r
-IBPP::Database RowImpl::DatabasePtr() const\r
-{\r
- return mDatabase;\r
-}\r
-\r
-IBPP::Transaction RowImpl::TransactionPtr() const\r
-{\r
- return mTransaction;\r
-}\r
-\r
-IBPP::IRow* RowImpl::Clone()\r
-{\r
- // By definition the clone of an IBPP Row is a new row (so refcount=0).\r
-\r
- RowImpl* clone = new RowImpl(*this);\r
- return clone;\r
-}\r
-\r
-IBPP::IRow* RowImpl::AddRef()\r
-{\r
- ASSERTION(mRefCount >= 0);\r
- ++mRefCount;\r
- return this;\r
-}\r
-\r
-void RowImpl::Release()\r
-{\r
- // Release cannot throw, except in DEBUG builds on assertion\r
- ASSERTION(mRefCount >= 0);\r
- --mRefCount;\r
- try { if (mRefCount <= 0) delete this; }\r
- catch (...) { }\r
-}\r
-\r
-// (((((((( OBJECT INTERNAL METHODS ))))))))\r
-\r
-void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen)\r
-{\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range."));\r
- if (value == 0)\r
- throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected."));\r
-\r
- int16_t len;\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_TEXT :\r
- if (ivType == ivString)\r
- {\r
- std::string* svalue = (std::string*)value;\r
- len = (int16_t)svalue->length();\r
- if (len > var->sqllen) len = var->sqllen;\r
- strncpy(var->sqldata, svalue->c_str(), len);\r
- while (len < var->sqllen) var->sqldata[len++] = ' ';\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- if (userlen > var->sqllen) userlen = var->sqllen;\r
- memcpy(var->sqldata, value, userlen);\r
- while (userlen < var->sqllen) var->sqldata[userlen++] = ' ';\r
- }\r
- else if (ivType == ivDBKey)\r
- {\r
- IBPP::DBKey* key = (IBPP::DBKey*)value;\r
- key->GetKey(var->sqldata, var->sqllen);\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- var->sqldata[0] = *(bool*)value ? 'T' : 'F';\r
- len = 1;\r
- while (len < var->sqllen) var->sqldata[len++] = ' ';\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_VARYING :\r
- if (ivType == ivString)\r
- {\r
- std::string* svalue = (std::string*)value;\r
- len = (int16_t)svalue->length();\r
- if (len > var->sqllen) len = var->sqllen;\r
- *(int16_t*)var->sqldata = (int16_t)len;\r
- strncpy(var->sqldata+2, svalue->c_str(), len);\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- if (userlen > var->sqllen) userlen = var->sqllen;\r
- *(int16_t*)var->sqldata = (int16_t)userlen;\r
- memcpy(var->sqldata+2, value, userlen);\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- *(int16_t*)var->sqldata = (int16_t)1;\r
- var->sqldata[2] = *(bool*)value ? 'T' : 'F';\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_SHORT :\r
- if (ivType == ivBool)\r
- {\r
- *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0);\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- *(int16_t*)var->sqldata = *(int16_t*)value;\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("Out of range numeric conversion !"));\r
- *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value;\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("Out of range numeric conversion !"));\r
- *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value;\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int16_t*)var->sqldata =\r
- (int16_t)floor(*(float*)value * multiplier + 0.5);\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int16_t*)var->sqldata =\r
- (int16_t)floor(*(double*)value * multiplier + 0.5);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_LONG :\r
- if (ivType == ivBool)\r
- {\r
- *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0;\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- *(ISC_LONG*)var->sqldata = *(int16_t*)value;\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value;\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32)\r
- throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("Out of range numeric conversion !"));\r
- *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value;\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(ISC_LONG*)var->sqldata =\r
- (ISC_LONG)floor(*(float*)value * multiplier + 0.5);\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(ISC_LONG*)var->sqldata =\r
- (ISC_LONG)floor(*(double*)value * multiplier + 0.5);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_INT64 :\r
- if (ivType == ivBool)\r
- {\r
- *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0;\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- *(int64_t*)var->sqldata = *(int16_t*)value;\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- *(int64_t*)var->sqldata = *(int32_t*)value;\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- *(int64_t*)var->sqldata = *(int64_t*)value;\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int64_t*)var->sqldata =\r
- (int64_t)floor(*(float*)value * multiplier + 0.5);\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(int64_t*)var->sqldata =\r
- (int64_t)floor(*(double*)value * multiplier + 0.5);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_FLOAT :\r
- if (ivType != ivFloat || var->sqlscale != 0)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- *(float*)var->sqldata = *(float*)value;\r
- break;\r
-\r
- case SQL_DOUBLE :\r
- if (ivType != ivDouble)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- if (var->sqlscale != 0)\r
- {\r
- // Round to scale of NUMERIC(x,y)\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- *(double*)var->sqldata =\r
- floor(*(double*)value * multiplier + 0.5) / multiplier;\r
- }\r
- else *(double*)var->sqldata = *(double*)value;\r
- break;\r
-\r
- case SQL_TIMESTAMP :\r
- if (ivType != ivTimestamp)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value);\r
- break;\r
-\r
- case SQL_TYPE_DATE :\r
- if (ivType != ivDate)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value);\r
- break;\r
-\r
- case SQL_TYPE_TIME :\r
- if (ivType != ivTime)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value);\r
- break;\r
-\r
- case SQL_BLOB :\r
- if (ivType == ivBlob)\r
- {\r
- BlobImpl* blob = (BlobImpl*)value;\r
- blob->GetId((ISC_QUAD*)var->sqldata);\r
- }\r
- else if (ivType == ivString)\r
- {\r
- BlobImpl blob(mDatabase, mTransaction);\r
- blob.Save(*(std::string*)value);\r
- blob.GetId((ISC_QUAD*)var->sqldata);\r
- }\r
- else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_ARRAY :\r
- if (ivType != ivArray)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- {\r
- ArrayImpl* array = (ArrayImpl*)value;\r
- array->GetId((ISC_QUAD*)var->sqldata);\r
- // When an array has been affected to a column, we want to reset\r
- // its ID. This way, the next WriteFrom() on the same Array object\r
- // will allocate a new ID. This protects against storing the same\r
- // array ID in multiple columns or rows.\r
- array->ResetId();\r
- }\r
- break;\r
-\r
- default : throw LogicExceptionImpl("RowImpl::SetValue",\r
- _("The field uses an unsupported SQL type !"));\r
- }\r
-\r
- if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag\r
-}\r
-\r
-void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue)\r
-{\r
- if (varnum < 1 || varnum > mDescrArea->sqld)\r
- throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range."));\r
-\r
- void* value;\r
- int len;\r
- XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);\r
-\r
- // When there is no value (SQL NULL)\r
- if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0;\r
-\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_TEXT :\r
- if (ivType == ivString)\r
- {\r
- // In case of ivString, 'void* retvalue' points to a std::string where we\r
- // will directly store the data.\r
- std::string* str = (std::string*)retvalue;\r
- str->erase();\r
- str->append(var->sqldata, var->sqllen);\r
- value = retvalue; // value != 0 means 'not null'\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- // In case of ivByte, void* retvalue points to an int where we\r
- // will store the len of the available data\r
- if (retvalue != 0) *(int*)retvalue = var->sqllen;\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivDBKey)\r
- {\r
- IBPP::DBKey* key = (IBPP::DBKey*)retvalue;\r
- key->SetKey(var->sqldata, var->sqllen);\r
- value = retvalue;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- mBools[varnum-1] = 0;\r
- if (var->sqllen >= 1)\r
- {\r
- char c = var->sqldata[0];\r
- if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
- mBools[varnum-1] = 1;\r
- }\r
- value = &mBools[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_VARYING :\r
- if (ivType == ivString)\r
- {\r
- // In case of ivString, 'void* retvalue' points to a std::string where we\r
- // will directly store the data.\r
- std::string* str = (std::string*)retvalue;\r
- str->erase();\r
- str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata);\r
- value = retvalue;\r
- }\r
- else if (ivType == ivByte)\r
- {\r
- // In case of ivByte, void* retvalue points to an int where we\r
- // will store the len of the available data\r
- if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata;\r
- value = var->sqldata+2;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- mBools[varnum-1] = 0;\r
- len = *(int16_t*)var->sqldata;\r
- if (len >= 1)\r
- {\r
- char c = var->sqldata[2];\r
- if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')\r
- mBools[varnum-1] = 1;\r
- }\r
- value = &mBools[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_SHORT :\r
- if (ivType == ivInt16)\r
- {\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
- else mBools[varnum-1] = 1;\r
- value = &mBools[varnum-1];\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- mInt32s[varnum-1] = *(int16_t*)var->sqldata;\r
- value = &mInt32s[varnum-1];\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- mInt64s[varnum-1] = *(int16_t*)var->sqldata;\r
- value = &mInt64s[varnum-1];\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor);\r
-\r
- value = &mFloats[varnum-1];\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_SHORT is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_LONG :\r
- if (ivType == ivInt32)\r
- {\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
- else mBools[varnum-1] = 1;\r
- value = &mBools[varnum-1];\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- int32_t tmp = *(int32_t*)var->sqldata;\r
- if (tmp < consts::min16 || tmp > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Out of range numeric conversion !"));\r
- mInt16s[varnum-1] = (int16_t)tmp;\r
- value = &mInt16s[varnum-1];\r
- }\r
- else if (ivType == ivInt64)\r
- {\r
- mInt64s[varnum-1] = *(int32_t*)var->sqldata;\r
- value = &mInt64s[varnum-1];\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor);\r
- value = &mFloats[varnum-1];\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_LONG is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_INT64 :\r
- if (ivType == ivInt64)\r
- {\r
- value = var->sqldata;\r
- }\r
- else if (ivType == ivBool)\r
- {\r
- if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0;\r
- else mBools[varnum-1] = 1;\r
- value = &mBools[varnum-1];\r
- }\r
- else if (ivType == ivInt16)\r
- {\r
- int64_t tmp = *(int64_t*)var->sqldata;\r
- if (tmp < consts::min16 || tmp > consts::max16)\r
- throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Out of range numeric conversion !"));\r
- mInt16s[varnum-1] = (int16_t)tmp;\r
- value = &mInt16s[varnum-1];\r
- }\r
- else if (ivType == ivInt32)\r
- {\r
- int64_t tmp = *(int64_t*)var->sqldata;\r
- if (tmp < consts::min32 || tmp > consts::max32)\r
- throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Out of range numeric conversion !"));\r
- mInt32s[varnum-1] = (int32_t)tmp;\r
- value = &mInt32s[varnum-1];\r
- }\r
- else if (ivType == ivFloat)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor);\r
- value = &mFloats[varnum-1];\r
- }\r
- else if (ivType == ivDouble)\r
- {\r
- // This SQL_INT64 is a NUMERIC(x,y), scale it !\r
- double divisor = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
-\r
- case SQL_FLOAT :\r
- if (ivType != ivFloat)\r
- throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- value = var->sqldata;\r
- break;\r
-\r
- case SQL_DOUBLE :\r
- if (ivType != ivDouble)\r
- throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- if (var->sqlscale != 0)\r
- {\r
- // Round to scale y of NUMERIC(x,y)\r
- double multiplier = consts::dscales[-var->sqlscale];\r
- mNumerics[varnum-1] =\r
- floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier;\r
- value = &mNumerics[varnum-1];\r
- }\r
- else value = var->sqldata;\r
- break;\r
-\r
- case SQL_TIMESTAMP :\r
- if (ivType != ivTimestamp)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata);\r
- value = retvalue;\r
- break;\r
-\r
- case SQL_TYPE_DATE :\r
- if (ivType != ivDate)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata);\r
- value = retvalue;\r
- break;\r
-\r
- case SQL_TYPE_TIME :\r
- if (ivType != ivTime)\r
- throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata);\r
- value = retvalue;\r
- break;\r
-\r
- case SQL_BLOB :\r
- if (ivType == ivBlob)\r
- {\r
- BlobImpl* blob = (BlobImpl*)retvalue;\r
- blob->SetId((ISC_QUAD*)var->sqldata);\r
- value = retvalue;\r
- }\r
- else if (ivType == ivString)\r
- {\r
- BlobImpl blob(mDatabase, mTransaction);\r
- blob.SetId((ISC_QUAD*)var->sqldata);\r
- std::string* str = (std::string*)retvalue;\r
- blob.Load(*str);\r
- value = retvalue;\r
- }\r
- else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- break;\r
- \r
- case SQL_ARRAY :\r
- if (ivType != ivArray)\r
- throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,\r
- _("Incompatible types."));\r
- {\r
- ArrayImpl* array = (ArrayImpl*)retvalue;\r
- array->SetId((ISC_QUAD*)var->sqldata);\r
- value = retvalue;\r
- }\r
- break;\r
-\r
- default : throw LogicExceptionImpl("RowImpl::GetValue",\r
- _("Found an unknown sqltype !"));\r
- }\r
-\r
- return value;\r
-}\r
-\r
-void RowImpl::Free()\r
-{\r
- if (mDescrArea != 0)\r
- {\r
- for (int i = 0; i < mDescrArea->sqln; i++)\r
- {\r
- XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
- if (var->sqldata != 0)\r
- {\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_ARRAY :\r
- case SQL_BLOB : delete (ISC_QUAD*) var->sqldata; break;\r
- case SQL_TIMESTAMP :delete (ISC_TIMESTAMP*) var->sqldata; break;\r
- case SQL_TYPE_TIME :delete (ISC_TIME*) var->sqldata; break;\r
- case SQL_TYPE_DATE :delete (ISC_DATE*) var->sqldata; break;\r
- case SQL_TEXT :\r
- case SQL_VARYING : delete [] var->sqldata; break;\r
- case SQL_SHORT : delete (int16_t*) var->sqldata; break;\r
- case SQL_LONG : delete (int32_t*) var->sqldata; break;\r
- case SQL_INT64 : delete (int64_t*) var->sqldata; break;\r
- case SQL_FLOAT : delete (float*) var->sqldata; break;\r
- case SQL_DOUBLE : delete (double*) var->sqldata; break;\r
- default : throw LogicExceptionImpl("RowImpl::Free",\r
- _("Found an unknown sqltype !"));\r
- }\r
- }\r
- if (var->sqlind != 0) delete var->sqlind;\r
- }\r
- delete [] (char*)mDescrArea;\r
- mDescrArea = 0;\r
- }\r
-\r
- mNumerics.clear();\r
- mFloats.clear();\r
- mInt64s.clear();\r
- mInt32s.clear();\r
- mInt16s.clear();\r
- mBools.clear();\r
- mStrings.clear();\r
- mUpdated.clear();\r
-\r
- mDialect = 0;\r
- mDatabase = 0;\r
- mTransaction = 0;\r
-}\r
-\r
-void RowImpl::Resize(int n)\r
-{\r
- const int size = XSQLDA_LENGTH(n);\r
-\r
- Free();\r
- mDescrArea = (XSQLDA*) new char[size];\r
-\r
- memset(mDescrArea, 0, size);\r
- mNumerics.resize(n);\r
- mFloats.resize(n);\r
- mInt64s.resize(n);\r
- mInt32s.resize(n);\r
- mInt16s.resize(n);\r
- mBools.resize(n);\r
- mStrings.resize(n);\r
- mUpdated.resize(n);\r
- for (int i = 0; i < n; i++)\r
- {\r
- mNumerics[i] = 0.0;\r
- mFloats[i] = 0.0;\r
- mInt64s[i] = 0;\r
- mInt32s[i] = 0;\r
- mInt16s[i] = 0;\r
- mBools[i] = 0;\r
- mStrings[i].erase();\r
- mUpdated[i] = false;\r
- }\r
-\r
- mDescrArea->version = SQLDA_VERSION1;\r
- mDescrArea->sqln = (int16_t)n;\r
-}\r
-\r
-void RowImpl::AllocVariables()\r
-{\r
- int i;\r
- for (i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_ARRAY :\r
- case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
- memset(var->sqldata, 0, sizeof(ISC_QUAD));\r
- break;\r
- case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
- memset(var->sqldata, 0, sizeof(ISC_TIMESTAMP));\r
- break;\r
- case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
- memset(var->sqldata, 0, sizeof(ISC_TIME));\r
- break;\r
- case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
- memset(var->sqldata, 0, sizeof(ISC_DATE));\r
- break;\r
- case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
- memset(var->sqldata, ' ', var->sqllen);\r
- var->sqldata[var->sqllen] = '\0';\r
- break;\r
- case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
- memset(var->sqldata, 0, 2);\r
- memset(var->sqldata+2, ' ', var->sqllen);\r
- var->sqldata[var->sqllen+2] = '\0';\r
- break;\r
- case SQL_SHORT : var->sqldata = (char*) new int16_t(0); break;\r
- case SQL_LONG : var->sqldata = (char*) new int32_t(0); break;\r
- case SQL_INT64 : var->sqldata = (char*) new int64_t(0); break;\r
- case SQL_FLOAT : var->sqldata = (char*) new float(0.0); break;\r
- case SQL_DOUBLE : var->sqldata = (char*) new double(0.0); break;\r
- default : throw LogicExceptionImpl("RowImpl::AllocVariables",\r
- _("Found an unknown sqltype !"));\r
- }\r
- if (var->sqltype & 1) var->sqlind = new short(-1); // 0 indicator\r
- }\r
-}\r
-\r
-bool RowImpl::MissingValues()\r
-{\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- if (! mUpdated[i]) return true;\r
- return false;\r
-}\r
-\r
-RowImpl& RowImpl::operator=(const RowImpl& copied)\r
-{\r
- Free();\r
-\r
- const int n = copied.mDescrArea->sqln;\r
- const int size = XSQLDA_LENGTH(n);\r
-\r
- // Initial brute copy\r
- mDescrArea = (XSQLDA*) new char[size];\r
- memcpy(mDescrArea, copied.mDescrArea, size);\r
-\r
- // Copy of the columns data\r
- for (int i = 0; i < mDescrArea->sqld; i++)\r
- {\r
- XSQLVAR* var = &(mDescrArea->sqlvar[i]);\r
- XSQLVAR* org = &(copied.mDescrArea->sqlvar[i]);\r
- switch (var->sqltype & ~1)\r
- {\r
- case SQL_ARRAY :\r
- case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_QUAD));\r
- break;\r
- case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIMESTAMP));\r
- break;\r
- case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIME));\r
- break;\r
- case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;\r
- memcpy(var->sqldata, org->sqldata, sizeof(ISC_DATE));\r
- break;\r
- case SQL_TEXT : var->sqldata = new char[var->sqllen+1];\r
- memcpy(var->sqldata, org->sqldata, var->sqllen+1);\r
- break;\r
- case SQL_VARYING : var->sqldata = new char[var->sqllen+3];\r
- memcpy(var->sqldata, org->sqldata, var->sqllen+3);\r
- break;\r
- case SQL_SHORT : var->sqldata = (char*) new int16_t(*(int16_t*)org->sqldata); break;\r
- case SQL_LONG : var->sqldata = (char*) new int32_t(*(int32_t*)org->sqldata); break;\r
- case SQL_INT64 : var->sqldata = (char*) new int64_t(*(int64_t*)org->sqldata); break;\r
- case SQL_FLOAT : var->sqldata = (char*) new float(*(float*)org->sqldata); break;\r
- case SQL_DOUBLE : var->sqldata = (char*) new double(*(double*)org->sqldata); break;\r
- default : throw LogicExceptionImpl("RowImpl::Ctor",\r
- _("Found an unknown sqltype !"));\r
- }\r
- if (var->sqltype & 1) var->sqlind = new short(*org->sqlind); // 0 indicator\r
- }\r
-\r
- // Pointers init, real data copy\r
- mNumerics = copied.mNumerics;\r
- mFloats = copied.mFloats;\r
- mInt64s = copied.mInt64s;\r
- mInt32s = copied.mInt32s;\r
- mInt16s = copied.mInt16s;\r
- mBools = copied.mBools;\r
- mStrings = copied.mStrings;\r
-\r
- mDialect = copied.mDialect;\r
- mDatabase = copied.mDatabase;\r
- mTransaction = copied.mTransaction;\r
- \r
- return *this;\r
-}\r
-\r
-RowImpl::RowImpl(const RowImpl& copied)\r
- : IBPP::IRow(), mRefCount(0), mDescrArea(0)\r
-{\r
- // mRefCount and mDescrArea are set to 0 before using the assignment operator\r
- *this = copied; // The assignment operator does the real copy\r
-}\r
-\r
-RowImpl::RowImpl(int dialect, int n, DatabaseImpl* db, TransactionImpl* tr)\r
- : mRefCount(0), mDescrArea(0)\r
-{\r
- Resize(n);\r
- mDialect = dialect;\r
- mDatabase = db;\r
- mTransaction = tr;\r
-}\r
-\r
-RowImpl::~RowImpl()\r
-{\r
- try { Free(); }\r
- catch (...) { }\r
-}\r
-\r
-//\r
-// EOF\r
-//\r