1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // File : $Id: row.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $
\r
4 // Subject : IBPP, Row class implementation
\r
6 ///////////////////////////////////////////////////////////////////////////////
\r
8 // (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org)
\r
10 // The contents of this file are subject to the IBPP License (the "License");
\r
11 // you may not use this file except in compliance with the License. You may
\r
12 // obtain a copy of the License at http://www.ibpp.org or in the 'license.txt'
\r
13 // file which must have been distributed along with this file.
\r
15 // This software, distributed under the License, is distributed on an "AS IS"
\r
16 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
\r
17 // License for the specific language governing rights and limitations
\r
18 // under the License.
\r
20 ///////////////////////////////////////////////////////////////////////////////
\r
23 // * Tabulations should be set every four characters when editing this file.
\r
25 ///////////////////////////////////////////////////////////////////////////////
\r
28 #pragma warning(disable: 4786 4996)
\r
30 #pragma warning(disable: 4702)
\r
44 using namespace ibpp_internals;
\r
46 // (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))
\r
48 void RowImpl::SetNull(int param)
\r
50 if (mDescrArea == 0)
\r
51 throw LogicExceptionImpl("Row::SetNull", _("The row is not initialized."));
\r
52 if (param < 1 || param > mDescrArea->sqld)
\r
53 throw LogicExceptionImpl("Row::SetNull", _("Variable index out of range."));
\r
55 XSQLVAR* var = &(mDescrArea->sqlvar[param-1]);
\r
56 if (! (var->sqltype & 1))
\r
57 throw LogicExceptionImpl("Row::SetNull", _("This column can't be null."));
\r
59 *var->sqlind = -1; // Set the column to SQL NULL
\r
60 mUpdated[param-1] = true;
\r
63 void RowImpl::Set(int param, bool value)
\r
65 if (mDescrArea == 0)
\r
66 throw LogicExceptionImpl("Row::Set[bool]", _("The row is not initialized."));
\r
68 SetValue(param, ivBool, &value);
\r
69 mUpdated[param-1] = true;
\r
72 void RowImpl::Set(int param, const char* cstring)
\r
74 if (mDescrArea == 0)
\r
75 throw LogicExceptionImpl("Row::Set[char*]", _("The row is not initialized."));
\r
77 throw LogicExceptionImpl("Row::Set[char*]", _("null char* pointer detected."));
\r
79 SetValue(param, ivByte, cstring, (int)strlen(cstring));
\r
80 mUpdated[param-1] = true;
\r
83 void RowImpl::Set(int param, const void* bindata, int len)
\r
85 if (mDescrArea == 0)
\r
86 throw LogicExceptionImpl("Row::Set[void*]", _("The row is not initialized."));
\r
88 throw LogicExceptionImpl("Row::Set[void*]", _("null char* pointer detected."));
\r
90 throw LogicExceptionImpl("Row::Set[void*]", _("Length must be >= 0"));
\r
92 SetValue(param, ivByte, bindata, len);
\r
93 mUpdated[param-1] = true;
\r
96 void RowImpl::Set(int param, const std::string& s)
\r
98 if (mDescrArea == 0)
\r
99 throw LogicExceptionImpl("Row::Set[string]", _("The row is not initialized."));
\r
101 SetValue(param, ivString, (void*)&s);
\r
102 mUpdated[param-1] = true;
\r
105 void RowImpl::Set(int param, int16_t value)
\r
107 if (mDescrArea == 0)
\r
108 throw LogicExceptionImpl("Row::Set[int16_t]", _("The row is not initialized."));
\r
110 SetValue(param, ivInt16, &value);
\r
111 mUpdated[param-1] = true;
\r
114 void RowImpl::Set(int param, int32_t value)
\r
116 if (mDescrArea == 0)
\r
117 throw LogicExceptionImpl("Row::Set[int32_t]", _("The row is not initialized."));
\r
119 SetValue(param, ivInt32, &value);
\r
120 mUpdated[param-1] = true;
\r
123 void RowImpl::Set(int param, int64_t value)
\r
125 if (mDescrArea == 0)
\r
126 throw LogicExceptionImpl("Row::Set[int64_t]", _("The row is not initialized."));
\r
128 SetValue(param, ivInt64, &value);
\r
129 mUpdated[param-1] = true;
\r
132 void RowImpl::Set(int param, float value)
\r
134 if (mDescrArea == 0)
\r
135 throw LogicExceptionImpl("Row::Set[float]", _("The row is not initialized."));
\r
137 SetValue(param, ivFloat, &value);
\r
138 mUpdated[param-1] = true;
\r
141 void RowImpl::Set(int param, double value)
\r
143 if (mDescrArea == 0)
\r
144 throw LogicExceptionImpl("Row::Set[double]", _("The row is not initialized."));
\r
146 SetValue(param, ivDouble, &value);
\r
147 mUpdated[param-1] = true;
\r
150 void RowImpl::Set(int param, const IBPP::Timestamp& value)
\r
152 if (mDescrArea == 0)
\r
153 throw LogicExceptionImpl("Row::Set[Timestamp]", _("The row is not initialized."));
\r
155 SetValue(param, ivTimestamp, &value);
\r
156 mUpdated[param-1] = true;
\r
159 void RowImpl::Set(int param, const IBPP::Date& value)
\r
161 if (mDescrArea == 0)
\r
162 throw LogicExceptionImpl("Row::Set[Date]", _("The row is not initialized."));
\r
166 // In dialect 1, IBPP::Date is supposed to work with old 'DATE'
\r
167 // fields which are actually ISC_TIMESTAMP.
\r
168 IBPP::Timestamp timestamp(value);
\r
169 SetValue(param, ivTimestamp, ×tamp);
\r
174 SetValue(param, ivDate, (void*)&value);
\r
177 mUpdated[param-1] = true;
\r
180 void RowImpl::Set(int param, const IBPP::Time& value)
\r
182 if (mDescrArea == 0)
\r
183 throw LogicExceptionImpl("Row::Set[Time]", _("The row is not initialized."));
\r
185 throw LogicExceptionImpl("Row::Set[Time]", _("Requires use of a dialect 3 database."));
\r
187 SetValue(param, ivTime, &value);
\r
188 mUpdated[param-1] = true;
\r
191 void RowImpl::Set(int param, const IBPP::Blob& blob)
\r
193 if (mDescrArea == 0)
\r
194 throw LogicExceptionImpl("Row::Set[Blob]", _("The row is not initialized."));
\r
195 if (mDatabase != 0 && blob->DatabasePtr() != mDatabase)
\r
196 throw LogicExceptionImpl("Row::Set[Blob]",
\r
197 _("IBlob and Row attached to different databases"));
\r
198 if (mTransaction != 0 && blob->TransactionPtr() != mTransaction)
\r
199 throw LogicExceptionImpl("Row::Set[Blob]",
\r
200 _("IBlob and Row attached to different transactions"));
\r
202 SetValue(param, ivBlob, blob.intf());
\r
203 mUpdated[param-1] = true;
\r
206 void RowImpl::Set(int param, const IBPP::Array& array)
\r
208 if (mDescrArea == 0)
\r
209 throw LogicExceptionImpl("Row::Set[Array]", _("The row is not initialized."));
\r
210 if (mDatabase != 0 && array->DatabasePtr() != mDatabase)
\r
211 throw LogicExceptionImpl("Row::Set[Array]",
\r
212 _("IArray and Row attached to different databases"));
\r
213 if (mTransaction != 0 && array->TransactionPtr() != mTransaction)
\r
214 throw LogicExceptionImpl("Row::Set[Array]",
\r
215 _("IArray and Row attached to different transactions"));
\r
217 SetValue(param, ivArray, (void*)array.intf());
\r
218 mUpdated[param-1] = true;
\r
221 void RowImpl::Set(int param, const IBPP::DBKey& key)
\r
223 if (mDescrArea == 0)
\r
224 throw LogicExceptionImpl("Row::Set[DBKey]", _("The row is not initialized."));
\r
226 SetValue(param, ivDBKey, (void*)&key);
\r
227 mUpdated[param-1] = true;
\r
231 void RowImpl::Set(int param, const IBPP::Value& value)
\r
233 if (mDescrArea == 0)
\r
234 throw LogicExceptionImpl("Row::Set[Value]", _("The row is not initialized."));
\r
236 //SetValue(param, ivDBKey, (void*)&key);
\r
237 //mUpdated[param-1] = true;
\r
241 bool RowImpl::IsNull(int column)
\r
243 if (mDescrArea == 0)
\r
244 throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));
\r
245 if (column < 1 || column > mDescrArea->sqld)
\r
246 throw LogicExceptionImpl("Row::IsNull", _("Variable index out of range."));
\r
248 XSQLVAR* var = &(mDescrArea->sqlvar[column-1]);
\r
249 return ((var->sqltype & 1) && *(var->sqlind) != 0) ? true : false;
\r
252 bool RowImpl::Get(int column, bool& retvalue)
\r
254 if (mDescrArea == 0)
\r
255 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
257 void* pvalue = GetValue(column, ivBool);
\r
259 retvalue = (*(char*)pvalue == 0 ? false : true);
\r
260 return pvalue == 0 ? true : false;
\r
263 bool RowImpl::Get(int column, char* retvalue)
\r
265 if (mDescrArea == 0)
\r
266 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
268 throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));
\r
271 void* pvalue = GetValue(column, ivByte, &sqllen);
\r
274 memcpy(retvalue, pvalue, sqllen);
\r
275 retvalue[sqllen] = '\0';
\r
277 return pvalue == 0 ? true : false;
\r
280 bool RowImpl::Get(int column, void* bindata, int& userlen)
\r
282 if (mDescrArea == 0)
\r
283 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
285 throw LogicExceptionImpl("Row::Get", _("Null pointer detected"));
\r
287 throw LogicExceptionImpl("Row::Get", _("Length must be >= 0"));
\r
290 void* pvalue = GetValue(column, ivByte, &sqllen);
\r
293 // userlen says how much bytes the user can accept
\r
294 // let's shorten it, if there is less bytes available
\r
295 if (sqllen < userlen) userlen = sqllen;
\r
296 memcpy(bindata, pvalue, userlen);
\r
298 return pvalue == 0 ? true : false;
\r
301 bool RowImpl::Get(int column, std::string& retvalue)
\r
303 if (mDescrArea == 0)
\r
304 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
306 void* pvalue = GetValue(column, ivString, &retvalue);
\r
307 return pvalue == 0 ? true : false;
\r
310 bool RowImpl::Get(int column, int16_t& retvalue)
\r
312 if (mDescrArea == 0)
\r
313 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
315 void* pvalue = GetValue(column, ivInt16);
\r
317 retvalue = *(int16_t*)pvalue;
\r
318 return pvalue == 0 ? true : false;
\r
321 bool RowImpl::Get(int column, int32_t& retvalue)
\r
323 if (mDescrArea == 0)
\r
324 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
326 void* pvalue = GetValue(column, ivInt32);
\r
328 retvalue = *(int32_t*)pvalue;
\r
329 return pvalue == 0 ? true : false;
\r
332 bool RowImpl::Get(int column, int64_t& retvalue)
\r
334 if (mDescrArea == 0)
\r
335 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
337 void* pvalue = GetValue(column, ivInt64);
\r
339 retvalue = *(int64_t*)pvalue;
\r
340 return pvalue == 0 ? true : false;
\r
343 bool RowImpl::Get(int column, float& retvalue)
\r
345 if (mDescrArea == 0)
\r
346 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
348 void* pvalue = GetValue(column, ivFloat);
\r
350 retvalue = *(float*)pvalue;
\r
351 return pvalue == 0 ? true : false;
\r
354 bool RowImpl::Get(int column, double& retvalue)
\r
356 if (mDescrArea == 0)
\r
357 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
359 void* pvalue = GetValue(column, ivDouble);
\r
361 retvalue = *(double*)pvalue;
\r
362 return pvalue == 0 ? true : false;
\r
365 bool RowImpl::Get(int column, IBPP::Timestamp& timestamp)
\r
367 if (mDescrArea == 0)
\r
368 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
370 void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);
\r
371 return pvalue == 0 ? true : false;
\r
374 bool RowImpl::Get(int column, IBPP::Date& date)
\r
376 if (mDescrArea == 0)
\r
377 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
381 // Dialect 1. IBPP::Date is supposed to work with old 'DATE'
\r
382 // fields which are actually ISC_TIMESTAMP.
\r
383 IBPP::Timestamp timestamp;
\r
384 void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp);
\r
385 if (pvalue != 0) date = timestamp;
\r
386 return pvalue == 0 ? true : false;
\r
390 void* pvalue = GetValue(column, ivDate, (void*)&date);
\r
391 return pvalue == 0 ? true : false;
\r
395 bool RowImpl::Get(int column, IBPP::Time& time)
\r
397 if (mDescrArea == 0)
\r
398 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
400 void* pvalue = GetValue(column, ivTime, (void*)&time);
\r
401 return pvalue == 0 ? true : false;
\r
404 bool RowImpl::Get(int column, IBPP::Blob& retblob)
\r
406 if (mDescrArea == 0)
\r
407 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
409 void* pvalue = GetValue(column, ivBlob, (void*)retblob.intf());
\r
410 return pvalue == 0 ? true : false;
\r
413 bool RowImpl::Get(int column, IBPP::DBKey& retkey)
\r
415 if (mDescrArea == 0)
\r
416 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
418 void* pvalue = GetValue(column, ivDBKey, (void*)&retkey);
\r
419 return pvalue == 0 ? true : false;
\r
422 bool RowImpl::Get(int column, IBPP::Array& retarray)
\r
424 if (mDescrArea == 0)
\r
425 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
427 void* pvalue = GetValue(column, ivArray, (void*)retarray.intf());
\r
428 return pvalue == 0 ? true : false;
\r
432 const IBPP::Value RowImpl::Get(int column)
\r
434 if (mDescrArea == 0)
\r
435 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
437 //void* value = GetValue(column, ivArray, (void*)retarray.intf());
\r
438 //return value == 0 ? true : false;
\r
439 return IBPP::Value();
\r
443 bool RowImpl::IsNull(const std::string& name)
\r
445 if (mDescrArea == 0)
\r
446 throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized."));
\r
448 return IsNull(ColumnNum(name));
\r
451 bool RowImpl::Get(const std::string& name, bool& retvalue)
\r
453 if (mDescrArea == 0)
\r
454 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
456 return Get(ColumnNum(name), retvalue);
\r
459 bool RowImpl::Get(const std::string& name, char* retvalue)
\r
461 if (mDescrArea == 0)
\r
462 throw LogicExceptionImpl("Row::Get[char*]", _("The row is not initialized."));
\r
464 return Get(ColumnNum(name), retvalue);
\r
467 bool RowImpl::Get(const std::string& name, void* retvalue, int& count)
\r
469 if (mDescrArea == 0)
\r
470 throw LogicExceptionImpl("Row::Get[void*,int]", _("The row is not initialized."));
\r
472 return Get(ColumnNum(name), retvalue, count);
\r
475 bool RowImpl::Get(const std::string& name, std::string& retvalue)
\r
477 if (mDescrArea == 0)
\r
478 throw LogicExceptionImpl("Row::GetString", _("The row is not initialized."));
\r
480 return Get(ColumnNum(name), retvalue);
\r
483 bool RowImpl::Get(const std::string& name, int16_t& retvalue)
\r
485 if (mDescrArea == 0)
\r
486 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
488 return Get(ColumnNum(name), retvalue);
\r
491 bool RowImpl::Get(const std::string& name, int32_t& retvalue)
\r
493 if (mDescrArea == 0)
\r
494 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
496 return Get(ColumnNum(name), retvalue);
\r
499 bool RowImpl::Get(const std::string& name, int64_t& retvalue)
\r
501 if (mDescrArea == 0)
\r
502 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
504 return Get(ColumnNum(name), retvalue);
\r
507 bool RowImpl::Get(const std::string& name, float& retvalue)
\r
509 if (mDescrArea == 0)
\r
510 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
512 return Get(ColumnNum(name), retvalue);
\r
515 bool RowImpl::Get(const std::string& name, double& retvalue)
\r
517 if (mDescrArea == 0)
\r
518 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
520 return Get(ColumnNum(name), retvalue);
\r
523 bool RowImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)
\r
525 if (mDescrArea == 0)
\r
526 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
528 return Get(ColumnNum(name), retvalue);
\r
531 bool RowImpl::Get(const std::string& name, IBPP::Date& retvalue)
\r
533 if (mDescrArea == 0)
\r
534 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
536 return Get(ColumnNum(name), retvalue);
\r
539 bool RowImpl::Get(const std::string& name, IBPP::Time& retvalue)
\r
541 if (mDescrArea == 0)
\r
542 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
544 return Get(ColumnNum(name), retvalue);
\r
547 bool RowImpl::Get(const std::string&name, IBPP::Blob& retblob)
\r
549 if (mDescrArea == 0)
\r
550 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
552 return Get(ColumnNum(name), retblob);
\r
555 bool RowImpl::Get(const std::string& name, IBPP::DBKey& retvalue)
\r
557 if (mDescrArea == 0)
\r
558 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
560 return Get(ColumnNum(name), retvalue);
\r
563 bool RowImpl::Get(const std::string& name, IBPP::Array& retarray)
\r
565 if (mDescrArea == 0)
\r
566 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
568 return Get(ColumnNum(name), retarray);
\r
572 const IBPP::Value RowImpl::Get(const std::string& name)
\r
574 if (mDescrArea == 0)
\r
575 throw LogicExceptionImpl("Row::Get", _("The row is not initialized."));
\r
577 return Get(ColumnNum(name));
\r
581 int RowImpl::Columns()
\r
583 if (mDescrArea == 0)
\r
584 throw LogicExceptionImpl("Row::Columns", _("The row is not initialized."));
\r
586 return mDescrArea->sqld;
\r
589 int RowImpl::ColumnNum(const std::string& name)
\r
591 if (mDescrArea == 0)
\r
592 throw LogicExceptionImpl("Row::ColumnNum", _("The row is not initialized."));
\r
594 throw LogicExceptionImpl("Row::ColumnNum", _("Column name <empty> not found."));
\r
597 char Uname[sizeof(var->sqlname)+1]; // Max size of sqlname + '\0'
\r
599 // Local upper case copy of the column name
\r
600 size_t len = name.length();
\r
601 if (len > sizeof(var->sqlname)) len = sizeof(var->sqlname);
\r
602 strncpy(Uname, name.c_str(), len);
\r
605 while (*p != '\0') { *p = char(toupper(*p)); ++p; }
\r
607 // Loop through the columns of the descriptor
\r
608 for (int i = 0; i < mDescrArea->sqld; i++)
\r
610 var = &(mDescrArea->sqlvar[i]);
\r
611 if (var->sqlname_length != (int16_t)len) continue;
\r
612 if (strncmp(Uname, var->sqlname, len) == 0) return i+1;
\r
615 // Failed finding the column name, let's retry using the aliases
\r
616 char Ualias[sizeof(var->aliasname)+1]; // Max size of aliasname + '\0'
\r
618 // Local upper case copy of the column name
\r
619 len = name.length();
\r
620 if (len > sizeof(var->aliasname)) len = sizeof(var->aliasname);
\r
621 strncpy(Ualias, name.c_str(), len);
\r
622 Ualias[len] = '\0';
\r
624 while (*p != '\0') { *p = char(toupper(*p)); ++p; }
\r
626 // Loop through the columns of the descriptor
\r
627 for (int i = 0; i < mDescrArea->sqld; i++)
\r
629 var = &(mDescrArea->sqlvar[i]);
\r
630 if (var->aliasname_length != (int16_t)len) continue;
\r
631 if (strncmp(Ualias, var->aliasname, len) == 0) return i+1;
\r
634 throw LogicExceptionImpl("Row::ColumnNum", _("Could not find matching column."));
\r
636 return 0; // DMC errronously warns here about a missing return
\r
641 ColumnName, ColumnAlias, ColumnTable : all these 3 have a mistake.
\r
642 Ideally, the strings should be stored elsewhere (like _Numerics and so on) to
\r
643 take into account the final '\0' which needs to be added. For now, we insert
\r
644 the '\0' in the original data, which will cut the 32th character. Not terribly
\r
645 bad, but should be cleanly rewritten.
\r
648 const char* RowImpl::ColumnName(int varnum)
\r
650 if (mDescrArea == 0)
\r
651 throw LogicExceptionImpl("Row::ColumnName", _("The row is not initialized."));
\r
652 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
653 throw LogicExceptionImpl("Row::ColumName", _("Variable index out of range."));
\r
655 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
656 if (var->sqlname_length >= 31) var->sqlname_length = 31;
\r
657 var->sqlname[var->sqlname_length] = '\0';
\r
658 return var->sqlname;
\r
661 const char* RowImpl::ColumnAlias(int varnum)
\r
663 if (mDescrArea == 0)
\r
664 throw LogicExceptionImpl("Row::ColumnAlias", _("The row is not initialized."));
\r
665 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
666 throw LogicExceptionImpl("Row::ColumnAlias", _("Variable index out of range."));
\r
668 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
669 if (var->aliasname_length >= 31) var->aliasname_length = 31;
\r
670 var->aliasname[var->aliasname_length] = '\0';
\r
671 return var->aliasname;
\r
674 const char* RowImpl::ColumnTable(int varnum)
\r
676 if (mDescrArea == 0)
\r
677 throw LogicExceptionImpl("Row::ColumnTable", _("The row is not initialized."));
\r
678 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
679 throw LogicExceptionImpl("Row::ColumnTable", _("Variable index out of range."));
\r
681 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
682 if (var->relname_length >= 31) var->relname_length = 31;
\r
683 var->relname[var->relname_length] = '\0';
\r
684 return var->relname;
\r
687 IBPP::SDT RowImpl::ColumnType(int varnum)
\r
689 if (mDescrArea == 0)
\r
690 throw LogicExceptionImpl("Row::ColumnType", _("The row is not initialized."));
\r
691 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
692 throw LogicExceptionImpl("Row::ColumnType", _("Variable index out of range."));
\r
695 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
697 switch (var->sqltype & ~1)
\r
699 case SQL_TEXT : value = IBPP::sdString; break;
\r
700 case SQL_VARYING : value = IBPP::sdString; break;
\r
701 case SQL_SHORT : value = IBPP::sdSmallint; break;
\r
702 case SQL_LONG : value = IBPP::sdInteger; break;
\r
703 case SQL_INT64 : value = IBPP::sdLargeint; break;
\r
704 case SQL_FLOAT : value = IBPP::sdFloat; break;
\r
705 case SQL_DOUBLE : value = IBPP::sdDouble; break;
\r
706 case SQL_TIMESTAMP : value = IBPP::sdTimestamp; break;
\r
707 case SQL_TYPE_DATE : value = IBPP::sdDate; break;
\r
708 case SQL_TYPE_TIME : value = IBPP::sdTime; break;
\r
709 case SQL_BLOB : value = IBPP::sdBlob; break;
\r
710 case SQL_ARRAY : value = IBPP::sdArray; break;
\r
711 default : throw LogicExceptionImpl("Row::ColumnType",
\r
712 _("Found an unknown sqltype !"));
\r
718 int RowImpl::ColumnSubtype(int varnum)
\r
720 if (mDescrArea == 0)
\r
721 throw LogicExceptionImpl("Row::ColumnSubtype", _("The row is not initialized."));
\r
722 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
723 throw LogicExceptionImpl("Row::ColumnSubtype", _("Variable index out of range."));
\r
725 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
726 return (int)var->sqlsubtype;
\r
729 int RowImpl::ColumnSize(int varnum)
\r
731 if (mDescrArea == 0)
\r
732 throw LogicExceptionImpl("Row::ColumnSize", _("The row is not initialized."));
\r
733 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
734 throw LogicExceptionImpl("Row::ColumnSize", _("Variable index out of range."));
\r
736 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
737 return var->sqllen;
\r
740 int RowImpl::ColumnScale(int varnum)
\r
742 if (mDescrArea == 0)
\r
743 throw LogicExceptionImpl("Row::ColumnScale", _("The row is not initialized."));
\r
744 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
745 throw LogicExceptionImpl("Row::ColumnScale", _("Variable index out of range."));
\r
747 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
748 return -var->sqlscale;
\r
751 bool RowImpl::ColumnUpdated(int varnum)
\r
753 if (mDescrArea == 0)
\r
754 throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));
\r
755 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
756 throw LogicExceptionImpl("Row::ColumnUpdated", _("Variable index out of range."));
\r
758 return mUpdated[varnum-1];
\r
761 bool RowImpl::Updated()
\r
763 if (mDescrArea == 0)
\r
764 throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized."));
\r
766 for (int i = 0; i < mDescrArea->sqld; i++)
\r
767 if (mUpdated[i]) return true;
\r
771 IBPP::Database RowImpl::DatabasePtr() const
\r
776 IBPP::Transaction RowImpl::TransactionPtr() const
\r
778 return mTransaction;
\r
781 IBPP::IRow* RowImpl::Clone()
\r
783 // By definition the clone of an IBPP Row is a new row (so refcount=0).
\r
785 RowImpl* clone = new RowImpl(*this);
\r
789 IBPP::IRow* RowImpl::AddRef()
\r
791 ASSERTION(mRefCount >= 0);
\r
796 void RowImpl::Release()
\r
798 // Release cannot throw, except in DEBUG builds on assertion
\r
799 ASSERTION(mRefCount >= 0);
\r
801 try { if (mRefCount <= 0) delete this; }
\r
805 // (((((((( OBJECT INTERNAL METHODS ))))))))
\r
807 void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen)
\r
809 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
810 throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range."));
\r
812 throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected."));
\r
815 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
816 switch (var->sqltype & ~1)
\r
819 if (ivType == ivString)
\r
821 std::string* svalue = (std::string*)value;
\r
822 len = (int16_t)svalue->length();
\r
823 if (len > var->sqllen) len = var->sqllen;
\r
824 strncpy(var->sqldata, svalue->c_str(), len);
\r
825 while (len < var->sqllen) var->sqldata[len++] = ' ';
\r
827 else if (ivType == ivByte)
\r
829 if (userlen > var->sqllen) userlen = var->sqllen;
\r
830 memcpy(var->sqldata, value, userlen);
\r
831 while (userlen < var->sqllen) var->sqldata[userlen++] = ' ';
\r
833 else if (ivType == ivDBKey)
\r
835 IBPP::DBKey* key = (IBPP::DBKey*)value;
\r
836 key->GetKey(var->sqldata, var->sqllen);
\r
838 else if (ivType == ivBool)
\r
840 var->sqldata[0] = *(bool*)value ? 'T' : 'F';
\r
842 while (len < var->sqllen) var->sqldata[len++] = ' ';
\r
844 else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
845 _("Incompatible types."));
\r
849 if (ivType == ivString)
\r
851 std::string* svalue = (std::string*)value;
\r
852 len = (int16_t)svalue->length();
\r
853 if (len > var->sqllen) len = var->sqllen;
\r
854 *(int16_t*)var->sqldata = (int16_t)len;
\r
855 strncpy(var->sqldata+2, svalue->c_str(), len);
\r
857 else if (ivType == ivByte)
\r
859 if (userlen > var->sqllen) userlen = var->sqllen;
\r
860 *(int16_t*)var->sqldata = (int16_t)userlen;
\r
861 memcpy(var->sqldata+2, value, userlen);
\r
863 else if (ivType == ivBool)
\r
865 *(int16_t*)var->sqldata = (int16_t)1;
\r
866 var->sqldata[2] = *(bool*)value ? 'T' : 'F';
\r
868 else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
869 _("Incompatible types."));
\r
873 if (ivType == ivBool)
\r
875 *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0);
\r
877 else if (ivType == ivInt16)
\r
879 *(int16_t*)var->sqldata = *(int16_t*)value;
\r
881 else if (ivType == ivInt32)
\r
883 if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16)
\r
884 throw LogicExceptionImpl("RowImpl::SetValue",
\r
885 _("Out of range numeric conversion !"));
\r
886 *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value;
\r
888 else if (ivType == ivInt64)
\r
890 if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16)
\r
891 throw LogicExceptionImpl("RowImpl::SetValue",
\r
892 _("Out of range numeric conversion !"));
\r
893 *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value;
\r
895 else if (ivType == ivFloat)
\r
897 // This SQL_SHORT is a NUMERIC(x,y), scale it !
\r
898 double multiplier = consts::dscales[-var->sqlscale];
\r
899 *(int16_t*)var->sqldata =
\r
900 (int16_t)floor(*(float*)value * multiplier + 0.5);
\r
902 else if (ivType == ivDouble)
\r
904 // This SQL_SHORT is a NUMERIC(x,y), scale it !
\r
905 double multiplier = consts::dscales[-var->sqlscale];
\r
906 *(int16_t*)var->sqldata =
\r
907 (int16_t)floor(*(double*)value * multiplier + 0.5);
\r
909 else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
910 _("Incompatible types."));
\r
914 if (ivType == ivBool)
\r
916 *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0;
\r
918 else if (ivType == ivInt16)
\r
920 *(ISC_LONG*)var->sqldata = *(int16_t*)value;
\r
922 else if (ivType == ivInt32)
\r
924 *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value;
\r
926 else if (ivType == ivInt64)
\r
928 if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32)
\r
929 throw LogicExceptionImpl("RowImpl::SetValue",
\r
930 _("Out of range numeric conversion !"));
\r
931 *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value;
\r
933 else if (ivType == ivFloat)
\r
935 // This SQL_LONG is a NUMERIC(x,y), scale it !
\r
936 double multiplier = consts::dscales[-var->sqlscale];
\r
937 *(ISC_LONG*)var->sqldata =
\r
938 (ISC_LONG)floor(*(float*)value * multiplier + 0.5);
\r
940 else if (ivType == ivDouble)
\r
942 // This SQL_LONG is a NUMERIC(x,y), scale it !
\r
943 double multiplier = consts::dscales[-var->sqlscale];
\r
944 *(ISC_LONG*)var->sqldata =
\r
945 (ISC_LONG)floor(*(double*)value * multiplier + 0.5);
\r
947 else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
948 _("Incompatible types."));
\r
952 if (ivType == ivBool)
\r
954 *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0;
\r
956 else if (ivType == ivInt16)
\r
958 *(int64_t*)var->sqldata = *(int16_t*)value;
\r
960 else if (ivType == ivInt32)
\r
962 *(int64_t*)var->sqldata = *(int32_t*)value;
\r
964 else if (ivType == ivInt64)
\r
966 *(int64_t*)var->sqldata = *(int64_t*)value;
\r
968 else if (ivType == ivFloat)
\r
970 // This SQL_INT64 is a NUMERIC(x,y), scale it !
\r
971 double multiplier = consts::dscales[-var->sqlscale];
\r
972 *(int64_t*)var->sqldata =
\r
973 (int64_t)floor(*(float*)value * multiplier + 0.5);
\r
975 else if (ivType == ivDouble)
\r
977 // This SQL_INT64 is a NUMERIC(x,y), scale it !
\r
978 double multiplier = consts::dscales[-var->sqlscale];
\r
979 *(int64_t*)var->sqldata =
\r
980 (int64_t)floor(*(double*)value * multiplier + 0.5);
\r
982 else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
983 _("Incompatible types."));
\r
987 if (ivType != ivFloat || var->sqlscale != 0)
\r
988 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
989 _("Incompatible types."));
\r
990 *(float*)var->sqldata = *(float*)value;
\r
994 if (ivType != ivDouble)
\r
995 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
996 _("Incompatible types."));
\r
997 if (var->sqlscale != 0)
\r
999 // Round to scale of NUMERIC(x,y)
\r
1000 double multiplier = consts::dscales[-var->sqlscale];
\r
1001 *(double*)var->sqldata =
\r
1002 floor(*(double*)value * multiplier + 0.5) / multiplier;
\r
1004 else *(double*)var->sqldata = *(double*)value;
\r
1007 case SQL_TIMESTAMP :
\r
1008 if (ivType != ivTimestamp)
\r
1009 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1010 _("Incompatible types."));
\r
1011 encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value);
\r
1014 case SQL_TYPE_DATE :
\r
1015 if (ivType != ivDate)
\r
1016 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1017 _("Incompatible types."));
\r
1018 encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value);
\r
1021 case SQL_TYPE_TIME :
\r
1022 if (ivType != ivTime)
\r
1023 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1024 _("Incompatible types."));
\r
1025 encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value);
\r
1029 if (ivType == ivBlob)
\r
1031 BlobImpl* blob = (BlobImpl*)value;
\r
1032 blob->GetId((ISC_QUAD*)var->sqldata);
\r
1034 else if (ivType == ivString)
\r
1036 BlobImpl blob(mDatabase, mTransaction);
\r
1037 blob.Save(*(std::string*)value);
\r
1038 blob.GetId((ISC_QUAD*)var->sqldata);
\r
1040 else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1041 _("Incompatible types."));
\r
1045 if (ivType != ivArray)
\r
1046 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1047 _("Incompatible types."));
\r
1049 ArrayImpl* array = (ArrayImpl*)value;
\r
1050 array->GetId((ISC_QUAD*)var->sqldata);
\r
1051 // When an array has been affected to a column, we want to reset
\r
1052 // its ID. This way, the next WriteFrom() on the same Array object
\r
1053 // will allocate a new ID. This protects against storing the same
\r
1054 // array ID in multiple columns or rows.
\r
1059 default : throw LogicExceptionImpl("RowImpl::SetValue",
\r
1060 _("The field uses an unsupported SQL type !"));
\r
1063 if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag
\r
1066 void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue)
\r
1068 if (varnum < 1 || varnum > mDescrArea->sqld)
\r
1069 throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range."));
\r
1073 XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]);
\r
1075 // When there is no value (SQL NULL)
\r
1076 if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0;
\r
1078 switch (var->sqltype & ~1)
\r
1081 if (ivType == ivString)
\r
1083 // In case of ivString, 'void* retvalue' points to a std::string where we
\r
1084 // will directly store the data.
\r
1085 std::string* str = (std::string*)retvalue;
\r
1087 str->append(var->sqldata, var->sqllen);
\r
1088 value = retvalue; // value != 0 means 'not null'
\r
1090 else if (ivType == ivByte)
\r
1092 // In case of ivByte, void* retvalue points to an int where we
\r
1093 // will store the len of the available data
\r
1094 if (retvalue != 0) *(int*)retvalue = var->sqllen;
\r
1095 value = var->sqldata;
\r
1097 else if (ivType == ivDBKey)
\r
1099 IBPP::DBKey* key = (IBPP::DBKey*)retvalue;
\r
1100 key->SetKey(var->sqldata, var->sqllen);
\r
1103 else if (ivType == ivBool)
\r
1105 mBools[varnum-1] = 0;
\r
1106 if (var->sqllen >= 1)
\r
1108 char c = var->sqldata[0];
\r
1109 if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')
\r
1110 mBools[varnum-1] = 1;
\r
1112 value = &mBools[varnum-1];
\r
1114 else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1115 _("Incompatible types."));
\r
1118 case SQL_VARYING :
\r
1119 if (ivType == ivString)
\r
1121 // In case of ivString, 'void* retvalue' points to a std::string where we
\r
1122 // will directly store the data.
\r
1123 std::string* str = (std::string*)retvalue;
\r
1125 str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata);
\r
1128 else if (ivType == ivByte)
\r
1130 // In case of ivByte, void* retvalue points to an int where we
\r
1131 // will store the len of the available data
\r
1132 if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata;
\r
1133 value = var->sqldata+2;
\r
1135 else if (ivType == ivBool)
\r
1137 mBools[varnum-1] = 0;
\r
1138 len = *(int16_t*)var->sqldata;
\r
1141 char c = var->sqldata[2];
\r
1142 if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1')
\r
1143 mBools[varnum-1] = 1;
\r
1145 value = &mBools[varnum-1];
\r
1147 else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1148 _("Incompatible types."));
\r
1152 if (ivType == ivInt16)
\r
1154 value = var->sqldata;
\r
1156 else if (ivType == ivBool)
\r
1158 if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0;
\r
1159 else mBools[varnum-1] = 1;
\r
1160 value = &mBools[varnum-1];
\r
1162 else if (ivType == ivInt32)
\r
1164 mInt32s[varnum-1] = *(int16_t*)var->sqldata;
\r
1165 value = &mInt32s[varnum-1];
\r
1167 else if (ivType == ivInt64)
\r
1169 mInt64s[varnum-1] = *(int16_t*)var->sqldata;
\r
1170 value = &mInt64s[varnum-1];
\r
1172 else if (ivType == ivFloat)
\r
1174 // This SQL_SHORT is a NUMERIC(x,y), scale it !
\r
1175 double divisor = consts::dscales[-var->sqlscale];
\r
1176 mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor);
\r
1178 value = &mFloats[varnum-1];
\r
1180 else if (ivType == ivDouble)
\r
1182 // This SQL_SHORT is a NUMERIC(x,y), scale it !
\r
1183 double divisor = consts::dscales[-var->sqlscale];
\r
1184 mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor;
\r
1185 value = &mNumerics[varnum-1];
\r
1187 else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1188 _("Incompatible types."));
\r
1192 if (ivType == ivInt32)
\r
1194 value = var->sqldata;
\r
1196 else if (ivType == ivBool)
\r
1198 if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0;
\r
1199 else mBools[varnum-1] = 1;
\r
1200 value = &mBools[varnum-1];
\r
1202 else if (ivType == ivInt16)
\r
1204 int32_t tmp = *(int32_t*)var->sqldata;
\r
1205 if (tmp < consts::min16 || tmp > consts::max16)
\r
1206 throw LogicExceptionImpl("RowImpl::GetValue",
\r
1207 _("Out of range numeric conversion !"));
\r
1208 mInt16s[varnum-1] = (int16_t)tmp;
\r
1209 value = &mInt16s[varnum-1];
\r
1211 else if (ivType == ivInt64)
\r
1213 mInt64s[varnum-1] = *(int32_t*)var->sqldata;
\r
1214 value = &mInt64s[varnum-1];
\r
1216 else if (ivType == ivFloat)
\r
1218 // This SQL_LONG is a NUMERIC(x,y), scale it !
\r
1219 double divisor = consts::dscales[-var->sqlscale];
\r
1220 mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor);
\r
1221 value = &mFloats[varnum-1];
\r
1223 else if (ivType == ivDouble)
\r
1225 // This SQL_LONG is a NUMERIC(x,y), scale it !
\r
1226 double divisor = consts::dscales[-var->sqlscale];
\r
1227 mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor;
\r
1228 value = &mNumerics[varnum-1];
\r
1230 else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1231 _("Incompatible types."));
\r
1235 if (ivType == ivInt64)
\r
1237 value = var->sqldata;
\r
1239 else if (ivType == ivBool)
\r
1241 if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0;
\r
1242 else mBools[varnum-1] = 1;
\r
1243 value = &mBools[varnum-1];
\r
1245 else if (ivType == ivInt16)
\r
1247 int64_t tmp = *(int64_t*)var->sqldata;
\r
1248 if (tmp < consts::min16 || tmp > consts::max16)
\r
1249 throw LogicExceptionImpl("RowImpl::GetValue",
\r
1250 _("Out of range numeric conversion !"));
\r
1251 mInt16s[varnum-1] = (int16_t)tmp;
\r
1252 value = &mInt16s[varnum-1];
\r
1254 else if (ivType == ivInt32)
\r
1256 int64_t tmp = *(int64_t*)var->sqldata;
\r
1257 if (tmp < consts::min32 || tmp > consts::max32)
\r
1258 throw LogicExceptionImpl("RowImpl::GetValue",
\r
1259 _("Out of range numeric conversion !"));
\r
1260 mInt32s[varnum-1] = (int32_t)tmp;
\r
1261 value = &mInt32s[varnum-1];
\r
1263 else if (ivType == ivFloat)
\r
1265 // This SQL_INT64 is a NUMERIC(x,y), scale it !
\r
1266 double divisor = consts::dscales[-var->sqlscale];
\r
1267 mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor);
\r
1268 value = &mFloats[varnum-1];
\r
1270 else if (ivType == ivDouble)
\r
1272 // This SQL_INT64 is a NUMERIC(x,y), scale it !
\r
1273 double divisor = consts::dscales[-var->sqlscale];
\r
1274 mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor;
\r
1275 value = &mNumerics[varnum-1];
\r
1277 else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1278 _("Incompatible types."));
\r
1282 if (ivType != ivFloat)
\r
1283 throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1284 _("Incompatible types."));
\r
1285 value = var->sqldata;
\r
1289 if (ivType != ivDouble)
\r
1290 throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1291 _("Incompatible types."));
\r
1292 if (var->sqlscale != 0)
\r
1294 // Round to scale y of NUMERIC(x,y)
\r
1295 double multiplier = consts::dscales[-var->sqlscale];
\r
1296 mNumerics[varnum-1] =
\r
1297 floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier;
\r
1298 value = &mNumerics[varnum-1];
\r
1300 else value = var->sqldata;
\r
1303 case SQL_TIMESTAMP :
\r
1304 if (ivType != ivTimestamp)
\r
1305 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1306 _("Incompatible types."));
\r
1307 decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata);
\r
1311 case SQL_TYPE_DATE :
\r
1312 if (ivType != ivDate)
\r
1313 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1314 _("Incompatible types."));
\r
1315 decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata);
\r
1319 case SQL_TYPE_TIME :
\r
1320 if (ivType != ivTime)
\r
1321 throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType,
\r
1322 _("Incompatible types."));
\r
1323 decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata);
\r
1328 if (ivType == ivBlob)
\r
1330 BlobImpl* blob = (BlobImpl*)retvalue;
\r
1331 blob->SetId((ISC_QUAD*)var->sqldata);
\r
1334 else if (ivType == ivString)
\r
1336 BlobImpl blob(mDatabase, mTransaction);
\r
1337 blob.SetId((ISC_QUAD*)var->sqldata);
\r
1338 std::string* str = (std::string*)retvalue;
\r
1342 else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1343 _("Incompatible types."));
\r
1347 if (ivType != ivArray)
\r
1348 throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType,
\r
1349 _("Incompatible types."));
\r
1351 ArrayImpl* array = (ArrayImpl*)retvalue;
\r
1352 array->SetId((ISC_QUAD*)var->sqldata);
\r
1357 default : throw LogicExceptionImpl("RowImpl::GetValue",
\r
1358 _("Found an unknown sqltype !"));
\r
1364 void RowImpl::Free()
\r
1366 if (mDescrArea != 0)
\r
1368 for (int i = 0; i < mDescrArea->sqln; i++)
\r
1370 XSQLVAR* var = &(mDescrArea->sqlvar[i]);
\r
1371 if (var->sqldata != 0)
\r
1373 switch (var->sqltype & ~1)
\r
1376 case SQL_BLOB : delete (ISC_QUAD*) var->sqldata; break;
\r
1377 case SQL_TIMESTAMP :delete (ISC_TIMESTAMP*) var->sqldata; break;
\r
1378 case SQL_TYPE_TIME :delete (ISC_TIME*) var->sqldata; break;
\r
1379 case SQL_TYPE_DATE :delete (ISC_DATE*) var->sqldata; break;
\r
1381 case SQL_VARYING : delete [] var->sqldata; break;
\r
1382 case SQL_SHORT : delete (int16_t*) var->sqldata; break;
\r
1383 case SQL_LONG : delete (int32_t*) var->sqldata; break;
\r
1384 case SQL_INT64 : delete (int64_t*) var->sqldata; break;
\r
1385 case SQL_FLOAT : delete (float*) var->sqldata; break;
\r
1386 case SQL_DOUBLE : delete (double*) var->sqldata; break;
\r
1387 default : throw LogicExceptionImpl("RowImpl::Free",
\r
1388 _("Found an unknown sqltype !"));
\r
1391 if (var->sqlind != 0) delete var->sqlind;
\r
1393 delete [] (char*)mDescrArea;
\r
1397 mNumerics.clear();
\r
1411 void RowImpl::Resize(int n)
\r
1413 const int size = XSQLDA_LENGTH(n);
\r
1416 mDescrArea = (XSQLDA*) new char[size];
\r
1418 memset(mDescrArea, 0, size);
\r
1419 mNumerics.resize(n);
\r
1420 mFloats.resize(n);
\r
1421 mInt64s.resize(n);
\r
1422 mInt32s.resize(n);
\r
1423 mInt16s.resize(n);
\r
1425 mStrings.resize(n);
\r
1426 mUpdated.resize(n);
\r
1427 for (int i = 0; i < n; i++)
\r
1429 mNumerics[i] = 0.0;
\r
1435 mStrings[i].erase();
\r
1436 mUpdated[i] = false;
\r
1439 mDescrArea->version = SQLDA_VERSION1;
\r
1440 mDescrArea->sqln = (int16_t)n;
\r
1443 void RowImpl::AllocVariables()
\r
1446 for (i = 0; i < mDescrArea->sqld; i++)
\r
1448 XSQLVAR* var = &(mDescrArea->sqlvar[i]);
\r
1449 switch (var->sqltype & ~1)
\r
1452 case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;
\r
1453 memset(var->sqldata, 0, sizeof(ISC_QUAD));
\r
1455 case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;
\r
1456 memset(var->sqldata, 0, sizeof(ISC_TIMESTAMP));
\r
1458 case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;
\r
1459 memset(var->sqldata, 0, sizeof(ISC_TIME));
\r
1461 case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;
\r
1462 memset(var->sqldata, 0, sizeof(ISC_DATE));
\r
1464 case SQL_TEXT : var->sqldata = new char[var->sqllen+1];
\r
1465 memset(var->sqldata, ' ', var->sqllen);
\r
1466 var->sqldata[var->sqllen] = '\0';
\r
1468 case SQL_VARYING : var->sqldata = new char[var->sqllen+3];
\r
1469 memset(var->sqldata, 0, 2);
\r
1470 memset(var->sqldata+2, ' ', var->sqllen);
\r
1471 var->sqldata[var->sqllen+2] = '\0';
\r
1473 case SQL_SHORT : var->sqldata = (char*) new int16_t(0); break;
\r
1474 case SQL_LONG : var->sqldata = (char*) new int32_t(0); break;
\r
1475 case SQL_INT64 : var->sqldata = (char*) new int64_t(0); break;
\r
1476 case SQL_FLOAT : var->sqldata = (char*) new float(0.0); break;
\r
1477 case SQL_DOUBLE : var->sqldata = (char*) new double(0.0); break;
\r
1478 default : throw LogicExceptionImpl("RowImpl::AllocVariables",
\r
1479 _("Found an unknown sqltype !"));
\r
1481 if (var->sqltype & 1) var->sqlind = new short(-1); // 0 indicator
\r
1485 bool RowImpl::MissingValues()
\r
1487 for (int i = 0; i < mDescrArea->sqld; i++)
\r
1488 if (! mUpdated[i]) return true;
\r
1492 RowImpl& RowImpl::operator=(const RowImpl& copied)
\r
1496 const int n = copied.mDescrArea->sqln;
\r
1497 const int size = XSQLDA_LENGTH(n);
\r
1499 // Initial brute copy
\r
1500 mDescrArea = (XSQLDA*) new char[size];
\r
1501 memcpy(mDescrArea, copied.mDescrArea, size);
\r
1503 // Copy of the columns data
\r
1504 for (int i = 0; i < mDescrArea->sqld; i++)
\r
1506 XSQLVAR* var = &(mDescrArea->sqlvar[i]);
\r
1507 XSQLVAR* org = &(copied.mDescrArea->sqlvar[i]);
\r
1508 switch (var->sqltype & ~1)
\r
1511 case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD;
\r
1512 memcpy(var->sqldata, org->sqldata, sizeof(ISC_QUAD));
\r
1514 case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP;
\r
1515 memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIMESTAMP));
\r
1517 case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME;
\r
1518 memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIME));
\r
1520 case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE;
\r
1521 memcpy(var->sqldata, org->sqldata, sizeof(ISC_DATE));
\r
1523 case SQL_TEXT : var->sqldata = new char[var->sqllen+1];
\r
1524 memcpy(var->sqldata, org->sqldata, var->sqllen+1);
\r
1526 case SQL_VARYING : var->sqldata = new char[var->sqllen+3];
\r
1527 memcpy(var->sqldata, org->sqldata, var->sqllen+3);
\r
1529 case SQL_SHORT : var->sqldata = (char*) new int16_t(*(int16_t*)org->sqldata); break;
\r
1530 case SQL_LONG : var->sqldata = (char*) new int32_t(*(int32_t*)org->sqldata); break;
\r
1531 case SQL_INT64 : var->sqldata = (char*) new int64_t(*(int64_t*)org->sqldata); break;
\r
1532 case SQL_FLOAT : var->sqldata = (char*) new float(*(float*)org->sqldata); break;
\r
1533 case SQL_DOUBLE : var->sqldata = (char*) new double(*(double*)org->sqldata); break;
\r
1534 default : throw LogicExceptionImpl("RowImpl::Ctor",
\r
1535 _("Found an unknown sqltype !"));
\r
1537 if (var->sqltype & 1) var->sqlind = new short(*org->sqlind); // 0 indicator
\r
1540 // Pointers init, real data copy
\r
1541 mNumerics = copied.mNumerics;
\r
1542 mFloats = copied.mFloats;
\r
1543 mInt64s = copied.mInt64s;
\r
1544 mInt32s = copied.mInt32s;
\r
1545 mInt16s = copied.mInt16s;
\r
1546 mBools = copied.mBools;
\r
1547 mStrings = copied.mStrings;
\r
1549 mDialect = copied.mDialect;
\r
1550 mDatabase = copied.mDatabase;
\r
1551 mTransaction = copied.mTransaction;
\r
1556 RowImpl::RowImpl(const RowImpl& copied)
\r
1557 : IBPP::IRow(), mRefCount(0), mDescrArea(0)
\r
1559 // mRefCount and mDescrArea are set to 0 before using the assignment operator
\r
1560 *this = copied; // The assignment operator does the real copy
\r
1563 RowImpl::RowImpl(int dialect, int n, DatabaseImpl* db, TransactionImpl* tr)
\r
1564 : mRefCount(0), mDescrArea(0)
\r
1567 mDialect = dialect;
\r
1569 mTransaction = tr;
\r
1572 RowImpl::~RowImpl()
\r