1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // File : $Id: statement.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $
\r
4 // Subject : IBPP, Service 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
42 using namespace ibpp_internals;
\r
44 // (((((((( OBJECT INTERFACE IMPLEMENTATION ))))))))
\r
46 void StatementImpl::Prepare(const std::string& sql)
\r
49 throw LogicExceptionImpl("Statement::Prepare", _("An IDatabase must be attached."));
\r
50 if (mDatabase->GetHandle() == 0)
\r
51 throw LogicExceptionImpl("Statement::Prepare", _("IDatabase must be connected."));
\r
52 if (mTransaction == 0)
\r
53 throw LogicExceptionImpl("Statement::Prepare", _("An ITransaction must be attached."));
\r
54 if (mTransaction->GetHandle() == 0)
\r
55 throw LogicExceptionImpl("Statement::Prepare", _("ITransaction must be started."));
\r
57 throw LogicExceptionImpl("Statement::Prepare", _("SQL statement can't be 0."));
\r
59 // Saves the SQL sentence, only for reporting reasons in case of errors
\r
64 // Free all resources currently attached to this Statement, then allocate
\r
65 // a new statement descriptor.
\r
67 (*gds.Call()->m_dsql_allocate_statement)(status.Self(), mDatabase->GetHandlePtr(), &mHandle);
\r
68 if (status.Errors())
\r
69 throw SQLExceptionImpl(status, "Statement::Prepare",
\r
70 _("isc_dsql_allocate_statement failed"));
\r
72 // Empirical estimate of parameters count and output columns count.
\r
73 // This is by far not an exact estimation, which would require parsing the
\r
74 // SQL statement. If the SQL statement contains '?' and ',' in string
\r
75 // constants, this count will obviously be wrong, but it will be exagerated.
\r
76 // It won't hurt. We just try to not have to re-allocate those descriptors later.
\r
77 // So we prefer to get them a little bit larger than needed than the other way.
\r
78 int16_t inEstimate = 0;
\r
79 int16_t outEstimate = 1;
\r
80 for (size_t i = 0; i < strlen(sql.c_str()); i++)
\r
82 if (sql[i] == '?') ++inEstimate;
\r
83 if (sql[i] == ',') ++outEstimate;
\r
87 DebugStream()<< "Prepare(\""<< sql<< "\")"<< fds;
\r
88 DebugStream()<< _("Estimation: ")<< inEstimate<< _(" IN parameters and ")
\r
89 << outEstimate<< _(" OUT columns")<< fds;
\r
92 // Allocates output descriptor and prepares the statement
\r
93 mOutRow = new RowImpl(mDatabase->Dialect(), outEstimate, mDatabase, mTransaction);
\r
97 (*gds.Call()->m_dsql_prepare)(status.Self(), mTransaction->GetHandlePtr(),
\r
98 &mHandle, (short)sql.length(), const_cast<char*>(sql.c_str()),
\r
99 short(mDatabase->Dialect()), mOutRow->Self());
\r
100 if (status.Errors())
\r
103 std::string context = "Statement::Prepare( ";
\r
104 context.append(mSql).append(" )");
\r
105 throw SQLExceptionImpl(status, context.c_str(),
\r
106 _("isc_dsql_prepare failed"));
\r
109 // Read what kind of statement was prepared
\r
111 char itemsReq[] = {isc_info_sql_stmt_type};
\r
113 (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,
\r
114 sizeof(itemsRes), itemsRes);
\r
115 if (status.Errors())
\r
118 throw SQLExceptionImpl(status, "Statement::Prepare",
\r
119 _("isc_dsql_sql_info failed"));
\r
121 if (itemsRes[0] == isc_info_sql_stmt_type)
\r
123 switch (itemsRes[3])
\r
125 case isc_info_sql_stmt_select : mType = IBPP::stSelect; break;
\r
126 case isc_info_sql_stmt_insert : mType = IBPP::stInsert; break;
\r
127 case isc_info_sql_stmt_update : mType = IBPP::stUpdate; break;
\r
128 case isc_info_sql_stmt_delete : mType = IBPP::stDelete; break;
\r
129 case isc_info_sql_stmt_ddl : mType = IBPP::stDDL; break;
\r
130 case isc_info_sql_stmt_exec_procedure : mType = IBPP::stExecProcedure; break;
\r
131 case isc_info_sql_stmt_select_for_upd : mType = IBPP::stSelectUpdate; break;
\r
132 case isc_info_sql_stmt_set_generator : mType = IBPP::stSetGenerator; break;
\r
133 case isc_info_sql_stmt_savepoint : mType = IBPP::stSavePoint; break;
\r
134 default : mType = IBPP::stUnsupported;
\r
137 if (mType == IBPP::stUnknown || mType == IBPP::stUnsupported)
\r
140 throw LogicExceptionImpl("Statement::Prepare",
\r
141 _("Unknown or unsupported statement type"));
\r
144 if (mOutRow->Columns() == 0)
\r
146 // Get rid of the output descriptor, if it wasn't required (no output)
\r
147 mOutRow->Release();
\r
150 DebugStream()<< _("Dropped output descriptor which was not required")<< fds;
\r
153 else if (mOutRow->Columns() > mOutRow->AllocatedSize())
\r
155 // Resize the output descriptor (which is too small).
\r
156 // The statement does not need to be prepared again, though the
\r
157 // output columns must be described again.
\r
160 DebugStream()<< _("Resize output descriptor from ")
\r
161 << mOutRow->AllocatedSize()<< _(" to ")<< mOutRow->Columns()<< fds;
\r
164 mOutRow->Resize(mOutRow->Columns());
\r
166 (*gds.Call()->m_dsql_describe)(status.Self(), &mHandle, 1, mOutRow->Self());
\r
167 if (status.Errors())
\r
170 throw SQLExceptionImpl(status, "Statement::Prepare",
\r
171 _("isc_dsql_describe failed"));
\r
175 if (inEstimate > 0)
\r
177 // Ready an input descriptor
\r
178 mInRow = new RowImpl(mDatabase->Dialect(), inEstimate, mDatabase, mTransaction);
\r
182 (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());
\r
183 if (status.Errors())
\r
186 throw SQLExceptionImpl(status, "Statement::Prepare",
\r
187 _("isc_dsql_describe_bind failed"));
\r
190 if (mInRow->Columns() == 0)
\r
192 // Get rid of the input descriptor, if it wasn't required (no parameters)
\r
196 DebugStream()<< _("Dropped input descriptor which was not required")<< fds;
\r
199 else if (mInRow->Columns() > mInRow->AllocatedSize())
\r
201 // Resize the input descriptor (which is too small).
\r
202 // The statement does not need to be prepared again, though the
\r
203 // parameters must be described again.
\r
206 DebugStream()<< _("Resize input descriptor from ")
\r
207 << mInRow->AllocatedSize()<< _(" to ")
\r
208 << mInRow->Columns()<< fds;
\r
211 mInRow->Resize(mInRow->Columns());
\r
213 (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self());
\r
214 if (status.Errors())
\r
217 throw SQLExceptionImpl(status, "Statement::Prepare",
\r
218 _("isc_dsql_describe_bind failed"));
\r
223 // Allocates variables of the input descriptor
\r
226 // Turn on 'can be NULL' on each input parameter
\r
227 for (int i = 0; i < mInRow->Columns(); i++)
\r
229 XSQLVAR* var = &(mInRow->Self()->sqlvar[i]);
\r
230 if (! (var->sqltype & 1)) var->sqltype += short(1);
\r
232 mInRow->AllocVariables();
\r
235 // Allocates variables of the output descriptor
\r
236 if (mOutRow != 0) mOutRow->AllocVariables();
\r
239 void StatementImpl::Plan(std::string& plan)
\r
242 throw LogicExceptionImpl("Statement::Plan", _("No statement has been prepared."));
\r
243 if (mDatabase == 0)
\r
244 throw LogicExceptionImpl("Statement::Plan", _("A Database must be attached."));
\r
245 if (mDatabase->GetHandle() == 0)
\r
246 throw LogicExceptionImpl("Statement::Plan", _("Database must be connected."));
\r
250 char itemsReq[] = {isc_info_sql_get_plan};
\r
252 (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,
\r
253 result.Size(), result.Self());
\r
254 if (status.Errors()) throw SQLExceptionImpl(status,
\r
255 "Statement::Plan", _("isc_dsql_sql_info failed."));
\r
257 result.GetString(isc_info_sql_get_plan, plan);
\r
258 if (plan[0] == '\n') plan.erase(0, 1);
\r
261 void StatementImpl::Execute(const std::string& sql)
\r
263 if (! sql.empty()) Prepare(sql);
\r
266 throw LogicExceptionImpl("Statement::Execute",
\r
267 _("No statement has been prepared."));
\r
269 // Check that a value has been set for each input parameter
\r
270 if (mInRow != 0 && mInRow->MissingValues())
\r
271 throw LogicExceptionImpl("Statement::Execute",
\r
272 _("All parameters must be specified."));
\r
274 CursorFree(); // Free a previous 'cursor' if any
\r
277 if (mType == IBPP::stSelect)
\r
279 // Could return a result set (none, single or multi rows)
\r
280 (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),
\r
281 &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());
\r
282 if (status.Errors())
\r
284 //Close(); Commented because Execute error should not free the statement
\r
285 std::string context = "Statement::Execute( ";
\r
286 context.append(mSql).append(" )");
\r
287 throw SQLExceptionImpl(status, context.c_str(),
\r
288 _("isc_dsql_execute failed"));
\r
292 mResultSetAvailable = true;
\r
293 mCursorOpened = true;
\r
298 // Should return at most a single row
\r
299 (*gds.Call()->m_dsql_execute2)(status.Self(), mTransaction->GetHandlePtr(),
\r
300 &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self(),
\r
301 mOutRow == 0 ? 0 : mOutRow->Self());
\r
302 if (status.Errors())
\r
304 //Close(); Commented because Execute error should not free the statement
\r
305 std::string context = "Statement::Execute( ";
\r
306 context.append(mSql).append(" )");
\r
307 throw SQLExceptionImpl(status, context.c_str(),
\r
308 _("isc_dsql_execute2 failed"));
\r
313 void StatementImpl::CursorExecute(const std::string& cursor, const std::string& sql)
\r
315 if (cursor.empty())
\r
316 throw LogicExceptionImpl("Statement::CursorExecute", _("Cursor name can't be 0."));
\r
318 if (! sql.empty()) Prepare(sql);
\r
321 throw LogicExceptionImpl("Statement::CursorExecute", _("No statement has been prepared."));
\r
322 if (mType != IBPP::stSelectUpdate)
\r
323 throw LogicExceptionImpl("Statement::CursorExecute", _("Statement must be a SELECT FOR UPDATE."));
\r
325 throw LogicExceptionImpl("Statement::CursorExecute", _("Statement would return no rows."));
\r
327 // Check that a value has been set for each input parameter
\r
328 if (mInRow != 0 && mInRow->MissingValues())
\r
329 throw LogicExceptionImpl("Statement::CursorExecute",
\r
330 _("All parameters must be specified."));
\r
332 CursorFree(); // Free a previous 'cursor' if any
\r
335 (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(),
\r
336 &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self());
\r
337 if (status.Errors())
\r
339 //Close(); Commented because Execute error should not free the statement
\r
340 std::string context = "Statement::CursorExecute( ";
\r
341 context.append(mSql).append(" )");
\r
342 throw SQLExceptionImpl(status, context.c_str(),
\r
343 _("isc_dsql_execute failed"));
\r
347 (*gds.Call()->m_dsql_set_cursor_name)(status.Self(), &mHandle, const_cast<char*>(cursor.c_str()), 0);
\r
348 if (status.Errors())
\r
350 //Close(); Commented because Execute error should not free the statement
\r
351 throw SQLExceptionImpl(status, "Statement::CursorExecute",
\r
352 _("isc_dsql_set_cursor_name failed"));
\r
355 mResultSetAvailable = true;
\r
356 mCursorOpened = true;
\r
359 void StatementImpl::ExecuteImmediate(const std::string& sql)
\r
361 if (mDatabase == 0)
\r
362 throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An IDatabase must be attached."));
\r
363 if (mDatabase->GetHandle() == 0)
\r
364 throw LogicExceptionImpl("Statement::ExecuteImmediate", _("IDatabase must be connected."));
\r
365 if (mTransaction == 0)
\r
366 throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An ITransaction must be attached."));
\r
367 if (mTransaction->GetHandle() == 0)
\r
368 throw LogicExceptionImpl("Statement::ExecuteImmediate", _("ITransaction must be started."));
\r
370 throw LogicExceptionImpl("Statement::ExecuteImmediate", _("SQL statement can't be 0."));
\r
374 (*gds.Call()->m_dsql_execute_immediate)(status.Self(), mDatabase->GetHandlePtr(),
\r
375 mTransaction->GetHandlePtr(), 0, const_cast<char*>(sql.c_str()),
\r
376 short(mDatabase->Dialect()), 0);
\r
377 if (status.Errors())
\r
379 std::string context = "Statement::ExecuteImmediate( ";
\r
380 context.append(sql).append(" )");
\r
381 throw SQLExceptionImpl(status, context.c_str(),
\r
382 _("isc_dsql_execute_immediate failed"));
\r
386 int StatementImpl::AffectedRows()
\r
389 throw LogicExceptionImpl("Statement::AffectedRows", _("No statement has been prepared."));
\r
390 if (mDatabase == 0)
\r
391 throw LogicExceptionImpl("Statement::AffectedRows", _("A Database must be attached."));
\r
392 if (mDatabase->GetHandle() == 0)
\r
393 throw LogicExceptionImpl("Statement::AffectedRows", _("Database must be connected."));
\r
398 char itemsReq[] = {isc_info_sql_records};
\r
400 (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq,
\r
401 result.Size(), result.Self());
\r
402 if (status.Errors()) throw SQLExceptionImpl(status,
\r
403 "Statement::AffectedRows", _("isc_dsql_sql_info failed."));
\r
405 if (mType == IBPP::stInsert)
\r
406 count = result.GetValue(isc_info_sql_records, isc_info_req_insert_count);
\r
407 else if (mType == IBPP::stUpdate)
\r
408 count = result.GetValue(isc_info_sql_records, isc_info_req_update_count);
\r
409 else if (mType == IBPP::stDelete)
\r
410 count = result.GetValue(isc_info_sql_records, isc_info_req_delete_count);
\r
411 else if (mType == IBPP::stSelect)
\r
412 count = result.GetValue(isc_info_sql_records, isc_info_req_select_count);
\r
413 else count = 0; // Returns zero count for unknown cases
\r
418 bool StatementImpl::Fetch()
\r
420 if (! mResultSetAvailable)
\r
421 throw LogicExceptionImpl("Statement::Fetch",
\r
422 _("No statement has been executed or no result set available."));
\r
425 ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1, mOutRow->Self());
\r
426 if (code == 100) // This special code means "no more rows"
\r
428 mResultSetAvailable = false;
\r
429 // Oddly enough, fetching rows up to the last one seems to open
\r
430 // an 'implicit' cursor that needs to be closed.
\r
431 mCursorOpened = true;
\r
432 CursorFree(); // Free the explicit or implicit cursor/result-set
\r
435 if (status.Errors())
\r
438 throw SQLExceptionImpl(status, "Statement::Fetch",
\r
439 _("isc_dsql_fetch failed."));
\r
445 bool StatementImpl::Fetch(IBPP::Row& row)
\r
447 if (! mResultSetAvailable)
\r
448 throw LogicExceptionImpl("Statement::Fetch(row)",
\r
449 _("No statement has been executed or no result set available."));
\r
451 RowImpl* rowimpl = new RowImpl(*mOutRow);
\r
455 ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1,
\r
457 if (code == 100) // This special code means "no more rows"
\r
459 mResultSetAvailable = false;
\r
460 // Oddly enough, fetching rows up to the last one seems to open
\r
461 // an 'implicit' cursor that needs to be closed.
\r
462 mCursorOpened = true;
\r
463 CursorFree(); // Free the explicit or implicit cursor/result-set
\r
467 if (status.Errors())
\r
471 throw SQLExceptionImpl(status, "Statement::Fetch(row)",
\r
472 _("isc_dsql_fetch failed."));
\r
478 void StatementImpl::Close()
\r
480 // Free all statement resources.
\r
481 // Used before preparing a new statement or from destructor.
\r
483 if (mInRow != 0) { mInRow->Release(); mInRow = 0; }
\r
484 if (mOutRow != 0) { mOutRow->Release(); mOutRow = 0; }
\r
486 mResultSetAvailable = false;
\r
487 mCursorOpened = false;
\r
488 mType = IBPP::stUnknown;
\r
493 (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_drop);
\r
495 if (status.Errors())
\r
496 throw SQLExceptionImpl(status, "Statement::Close(DSQL_drop)",
\r
497 _("isc_dsql_free_statement failed."));
\r
501 void StatementImpl::SetNull(int param)
\r
504 throw LogicExceptionImpl("Statement::SetNull", _("No statement has been prepared."));
\r
506 throw LogicExceptionImpl("Statement::SetNull", _("The statement does not take parameters."));
\r
508 mInRow->SetNull(param);
\r
511 void StatementImpl::Set(int param, bool value)
\r
514 throw LogicExceptionImpl("Statement::Set[bool]", _("No statement has been prepared."));
\r
516 throw LogicExceptionImpl("Statement::Set[bool]", _("The statement does not take parameters."));
\r
518 mInRow->Set(param, value);
\r
521 void StatementImpl::Set(int param, const char* cstring)
\r
524 throw LogicExceptionImpl("Statement::Set[char*]", _("No statement has been prepared."));
\r
526 throw LogicExceptionImpl("Statement::Set[char*]", _("The statement does not take parameters."));
\r
528 mInRow->Set(param, cstring);
\r
531 void StatementImpl::Set(int param, const void* bindata, int len)
\r
534 throw LogicExceptionImpl("Statement::Set[void*]", _("No statement has been prepared."));
\r
536 throw LogicExceptionImpl("Statement::Set[void*]", _("The statement does not take parameters."));
\r
538 mInRow->Set(param, bindata, len);
\r
541 void StatementImpl::Set(int param, const std::string& s)
\r
544 throw LogicExceptionImpl("Statement::Set[string]", _("No statement has been prepared."));
\r
546 throw LogicExceptionImpl("Statement::Set[string]", _("The statement does not take parameters."));
\r
548 mInRow->Set(param, s);
\r
551 void StatementImpl::Set(int param, int16_t value)
\r
554 throw LogicExceptionImpl("Statement::Set[int16_t]", _("No statement has been prepared."));
\r
556 throw LogicExceptionImpl("Statement::Set[int16_t]", _("The statement does not take parameters."));
\r
558 mInRow->Set(param, value);
\r
561 void StatementImpl::Set(int param, int32_t value)
\r
564 throw LogicExceptionImpl("Statement::Set[int32_t]", _("No statement has been prepared."));
\r
566 throw LogicExceptionImpl("Statement::Set[int32_t]", _("The statement does not take parameters."));
\r
568 mInRow->Set(param, value);
\r
571 void StatementImpl::Set(int param, int64_t value)
\r
574 throw LogicExceptionImpl("Statement::Set[int64_t]", _("No statement has been prepared."));
\r
576 throw LogicExceptionImpl("Statement::Set[int64_t]", _("The statement does not take parameters."));
\r
578 mInRow->Set(param, value);
\r
581 void StatementImpl::Set(int param, float value)
\r
584 throw LogicExceptionImpl("Statement::Set[float]", _("No statement has been prepared."));
\r
586 throw LogicExceptionImpl("Statement::Set[float]", _("The statement does not take parameters."));
\r
588 mInRow->Set(param, value);
\r
591 void StatementImpl::Set(int param, double value)
\r
594 throw LogicExceptionImpl("Statement::Set[double]", _("No statement has been prepared."));
\r
596 throw LogicExceptionImpl("Statement::Set[double]", _("The statement does not take parameters."));
\r
598 mInRow->Set(param, value);
\r
601 void StatementImpl::Set(int param, const IBPP::Timestamp& value)
\r
604 throw LogicExceptionImpl("Statement::Set[Timestamp]", _("No statement has been prepared."));
\r
606 throw LogicExceptionImpl("Statement::Set[Timestamp]", _("The statement does not take parameters."));
\r
608 mInRow->Set(param, value);
\r
611 void StatementImpl::Set(int param, const IBPP::Date& value)
\r
614 throw LogicExceptionImpl("Statement::Set[Date]", _("No statement has been prepared."));
\r
616 throw LogicExceptionImpl("Statement::Set[Date]", _("The statement does not take parameters."));
\r
618 mInRow->Set(param, value);
\r
621 void StatementImpl::Set(int param, const IBPP::Time& value)
\r
624 throw LogicExceptionImpl("Statement::Set[Time]", _("No statement has been prepared."));
\r
626 throw LogicExceptionImpl("Statement::Set[Time]", _("The statement does not take parameters."));
\r
628 mInRow->Set(param, value);
\r
631 void StatementImpl::Set(int param, const IBPP::Blob& blob)
\r
634 throw LogicExceptionImpl("Statement::Set[Blob]", _("No statement has been prepared."));
\r
636 throw LogicExceptionImpl("Statement::Set[Blob]", _("The statement does not take parameters."));
\r
638 mInRow->Set(param, blob);
\r
641 void StatementImpl::Set(int param, const IBPP::Array& array)
\r
644 throw LogicExceptionImpl("Statement::Set[Array]", _("No statement has been prepared."));
\r
646 throw LogicExceptionImpl("Statement::Set[Array]", _("The statement does not take parameters."));
\r
648 mInRow->Set(param, array);
\r
651 void StatementImpl::Set(int param, const IBPP::DBKey& key)
\r
654 throw LogicExceptionImpl("Statement::Set[DBKey]", _("No statement has been prepared."));
\r
656 throw LogicExceptionImpl("Statement::Set[DBKey]", _("The statement does not take parameters."));
\r
658 mInRow->Set(param, key);
\r
662 void StatementImpl::Set(int param, const IBPP::Value& value)
\r
665 throw LogicExceptionImpl("Statement::Set[Value]", _("No statement has been prepared."));
\r
667 throw LogicExceptionImpl("Statement::Set[Value]", _("The statement does not take parameters."));
\r
669 mInRow->Set(param, value);
\r
673 bool StatementImpl::IsNull(int column)
\r
676 throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));
\r
678 return mOutRow->IsNull(column);
\r
681 bool StatementImpl::Get(int column, bool* retvalue)
\r
684 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
686 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
688 return mOutRow->Get(column, *retvalue);
\r
691 bool StatementImpl::Get(int column, bool& retvalue)
\r
694 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
696 return mOutRow->Get(column, retvalue);
\r
699 bool StatementImpl::Get(int column, char* retvalue)
\r
702 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
704 return mOutRow->Get(column, retvalue);
\r
707 bool StatementImpl::Get(int column, void* bindata, int& userlen)
\r
710 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
712 return mOutRow->Get(column, bindata, userlen);
\r
715 bool StatementImpl::Get(int column, std::string& retvalue)
\r
718 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
720 return mOutRow->Get(column, retvalue);
\r
723 bool StatementImpl::Get(int column, int16_t* retvalue)
\r
726 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
728 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
730 return mOutRow->Get(column, *retvalue);
\r
733 bool StatementImpl::Get(int column, int16_t& retvalue)
\r
736 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
738 return mOutRow->Get(column, retvalue);
\r
741 bool StatementImpl::Get(int column, int32_t* retvalue)
\r
744 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
746 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
748 return mOutRow->Get(column, *retvalue);
\r
751 bool StatementImpl::Get(int column, int32_t& retvalue)
\r
754 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
756 return mOutRow->Get(column, retvalue);
\r
759 bool StatementImpl::Get(int column, int64_t* retvalue)
\r
762 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
764 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
766 return mOutRow->Get(column, *retvalue);
\r
769 bool StatementImpl::Get(int column, int64_t& retvalue)
\r
772 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
774 return mOutRow->Get(column, retvalue);
\r
777 bool StatementImpl::Get(int column, float* retvalue)
\r
780 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
782 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
784 return mOutRow->Get(column, *retvalue);
\r
787 bool StatementImpl::Get(int column, float& retvalue)
\r
790 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
792 return mOutRow->Get(column, retvalue);
\r
795 bool StatementImpl::Get(int column, double* retvalue)
\r
798 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
800 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
802 return mOutRow->Get(column, *retvalue);
\r
805 bool StatementImpl::Get(int column, double& retvalue)
\r
808 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
810 return mOutRow->Get(column, retvalue);
\r
813 bool StatementImpl::Get(int column, IBPP::Timestamp& timestamp)
\r
816 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
818 return mOutRow->Get(column, timestamp);
\r
821 bool StatementImpl::Get(int column, IBPP::Date& date)
\r
824 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
826 return mOutRow->Get(column, date);
\r
829 bool StatementImpl::Get(int column, IBPP::Time& time)
\r
832 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
834 return mOutRow->Get(column, time);
\r
837 bool StatementImpl::Get(int column, IBPP::Blob& blob)
\r
840 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
842 return mOutRow->Get(column, blob);
\r
845 bool StatementImpl::Get(int column, IBPP::DBKey& key)
\r
848 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
850 return mOutRow->Get(column, key);
\r
853 bool StatementImpl::Get(int column, IBPP::Array& array)
\r
856 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
858 return mOutRow->Get(column, array);
\r
862 const IBPP::Value StatementImpl::Get(int column)
\r
865 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
867 return mOutRow->Get(column);
\r
871 bool StatementImpl::IsNull(const std::string& name)
\r
874 throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized."));
\r
876 return mOutRow->IsNull(name);
\r
879 bool StatementImpl::Get(const std::string& name, bool* retvalue)
\r
882 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
884 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
886 return mOutRow->Get(name, *retvalue);
\r
889 bool StatementImpl::Get(const std::string& name, bool& retvalue)
\r
892 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
894 return mOutRow->Get(name, retvalue);
\r
897 bool StatementImpl::Get(const std::string& name, char* retvalue)
\r
900 throw LogicExceptionImpl("Statement::Get[char*]", _("The row is not initialized."));
\r
902 return mOutRow->Get(name, retvalue);
\r
905 bool StatementImpl::Get(const std::string& name, void* retvalue, int& count)
\r
908 throw LogicExceptionImpl("Statement::Get[void*,int]", _("The row is not initialized."));
\r
910 return mOutRow->Get(name, retvalue, count);
\r
913 bool StatementImpl::Get(const std::string& name, std::string& retvalue)
\r
916 throw LogicExceptionImpl("Statement::GetString", _("The row is not initialized."));
\r
918 return mOutRow->Get(name, retvalue);
\r
921 bool StatementImpl::Get(const std::string& name, int16_t* retvalue)
\r
924 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
926 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
928 return mOutRow->Get(name, *retvalue);
\r
931 bool StatementImpl::Get(const std::string& name, int16_t& retvalue)
\r
934 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
936 return mOutRow->Get(name, retvalue);
\r
939 bool StatementImpl::Get(const std::string& name, int32_t* retvalue)
\r
942 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
944 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
946 return mOutRow->Get(name, *retvalue);
\r
949 bool StatementImpl::Get(const std::string& name, int32_t& retvalue)
\r
952 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
954 return mOutRow->Get(name, retvalue);
\r
957 bool StatementImpl::Get(const std::string& name, int64_t* retvalue)
\r
960 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
962 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
964 return mOutRow->Get(name, *retvalue);
\r
967 bool StatementImpl::Get(const std::string& name, int64_t& retvalue)
\r
970 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
972 return mOutRow->Get(name, retvalue);
\r
975 bool StatementImpl::Get(const std::string& name, float* retvalue)
\r
978 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
980 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
982 return mOutRow->Get(name, *retvalue);
\r
985 bool StatementImpl::Get(const std::string& name, float& retvalue)
\r
988 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
990 return mOutRow->Get(name, retvalue);
\r
993 bool StatementImpl::Get(const std::string& name, double* retvalue)
\r
996 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
998 throw LogicExceptionImpl("Statement::Get", _("Null pointer detected"));
\r
1000 return mOutRow->Get(name, *retvalue);
\r
1003 bool StatementImpl::Get(const std::string& name, double& retvalue)
\r
1006 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1008 return mOutRow->Get(name, retvalue);
\r
1011 bool StatementImpl::Get(const std::string& name, IBPP::Timestamp& retvalue)
\r
1014 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1016 return mOutRow->Get(name, retvalue);
\r
1019 bool StatementImpl::Get(const std::string& name, IBPP::Date& retvalue)
\r
1022 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1024 return mOutRow->Get(name, retvalue);
\r
1027 bool StatementImpl::Get(const std::string& name, IBPP::Time& retvalue)
\r
1030 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1032 return mOutRow->Get(name, retvalue);
\r
1035 bool StatementImpl::Get(const std::string&name, IBPP::Blob& retblob)
\r
1038 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1040 return mOutRow->Get(name, retblob);
\r
1043 bool StatementImpl::Get(const std::string& name, IBPP::DBKey& retvalue)
\r
1046 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1048 return mOutRow->Get(name, retvalue);
\r
1051 bool StatementImpl::Get(const std::string& name, IBPP::Array& retarray)
\r
1054 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1056 return mOutRow->Get(name, retarray);
\r
1060 const IBPP::Value StatementImpl::Get(const std::string& name)
\r
1063 throw LogicExceptionImpl("Statement::Get", _("The row is not initialized."));
\r
1065 return mOutRow->Get(name);
\r
1069 int StatementImpl::Columns()
\r
1072 throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));
\r
1074 return mOutRow->Columns();
\r
1077 int StatementImpl::ColumnNum(const std::string& name)
\r
1080 throw LogicExceptionImpl("Statement::ColumnNum", _("The row is not initialized."));
\r
1082 return mOutRow->ColumnNum(name);
\r
1085 const char* StatementImpl::ColumnName(int varnum)
\r
1088 throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));
\r
1090 return mOutRow->ColumnName(varnum);
\r
1093 const char* StatementImpl::ColumnAlias(int varnum)
\r
1096 throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));
\r
1098 return mOutRow->ColumnAlias(varnum);
\r
1101 const char* StatementImpl::ColumnTable(int varnum)
\r
1104 throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized."));
\r
1106 return mOutRow->ColumnTable(varnum);
\r
1109 IBPP::SDT StatementImpl::ColumnType(int varnum)
\r
1112 throw LogicExceptionImpl("Statement::ColumnType", _("No statement has been prepared."));
\r
1114 throw LogicExceptionImpl("Statement::ColumnType", _("The statement does not return results."));
\r
1116 return mOutRow->ColumnType(varnum);
\r
1119 int StatementImpl::ColumnSubtype(int varnum)
\r
1122 throw LogicExceptionImpl("Statement::ColumnSubtype", _("No statement has been prepared."));
\r
1124 throw LogicExceptionImpl("Statement::ColumnSubtype", _("The statement does not return results."));
\r
1126 return mOutRow->ColumnSubtype(varnum);
\r
1129 int StatementImpl::ColumnSize(int varnum)
\r
1132 throw LogicExceptionImpl("Statement::ColumnSize", _("No statement has been prepared."));
\r
1134 throw LogicExceptionImpl("Statement::ColumnSize", _("The row is not initialized."));
\r
1136 return mOutRow->ColumnSize(varnum);
\r
1139 int StatementImpl::ColumnScale(int varnum)
\r
1142 throw LogicExceptionImpl("Statement::ColumnScale", _("No statement has been prepared."));
\r
1144 throw LogicExceptionImpl("Statement::ColumnScale", _("The row is not initialized."));
\r
1146 return mOutRow->ColumnScale(varnum);
\r
1149 int StatementImpl::Parameters()
\r
1152 throw LogicExceptionImpl("Statement::Parameters", _("No statement has been prepared."));
\r
1154 throw LogicExceptionImpl("Statement::Parameters", _("The statement uses no parameters."));
\r
1156 return mInRow->Columns();
\r
1159 IBPP::SDT StatementImpl::ParameterType(int varnum)
\r
1162 throw LogicExceptionImpl("Statement::ParameterType", _("No statement has been prepared."));
\r
1164 throw LogicExceptionImpl("Statement::ParameterType", _("The statement uses no parameters."));
\r
1166 return mInRow->ColumnType(varnum);
\r
1169 int StatementImpl::ParameterSubtype(int varnum)
\r
1172 throw LogicExceptionImpl("Statement::ParameterSubtype", _("No statement has been prepared."));
\r
1174 throw LogicExceptionImpl("Statement::ParameterSubtype", _("The statement uses no parameters."));
\r
1176 return mInRow->ColumnSubtype(varnum);
\r
1179 int StatementImpl::ParameterSize(int varnum)
\r
1182 throw LogicExceptionImpl("Statement::ParameterSize", _("No statement has been prepared."));
\r
1184 throw LogicExceptionImpl("Statement::ParameterSize", _("The statement uses no parameters."));
\r
1186 return mInRow->ColumnSize(varnum);
\r
1189 int StatementImpl::ParameterScale(int varnum)
\r
1192 throw LogicExceptionImpl("Statement::ParameterScale", _("No statement has been prepared."));
\r
1194 throw LogicExceptionImpl("Statement::ParameterScale", _("The statement uses no parameters."));
\r
1196 return mInRow->ColumnScale(varnum);
\r
1199 IBPP::Database StatementImpl::DatabasePtr() const
\r
1204 IBPP::Transaction StatementImpl::TransactionPtr() const
\r
1206 return mTransaction;
\r
1209 IBPP::IStatement* StatementImpl::AddRef()
\r
1211 ASSERTION(mRefCount >= 0);
\r
1217 void StatementImpl::Release()
\r
1219 // Release cannot throw, except in DEBUG builds on assertion
\r
1220 ASSERTION(mRefCount >= 0);
\r
1222 try { if (mRefCount <= 0) delete this; }
\r
1226 // (((((((( OBJECT INTERNAL METHODS ))))))))
\r
1228 void StatementImpl::AttachDatabaseImpl(DatabaseImpl* database)
\r
1230 if (database == 0)
\r
1231 throw LogicExceptionImpl("Statement::AttachDatabase",
\r
1232 _("Can't attach a 0 IDatabase object."));
\r
1234 if (mDatabase != 0) mDatabase->DetachStatementImpl(this);
\r
1235 mDatabase = database;
\r
1236 mDatabase->AttachStatementImpl(this);
\r
1239 void StatementImpl::DetachDatabaseImpl()
\r
1241 if (mDatabase == 0) return;
\r
1244 mDatabase->DetachStatementImpl(this);
\r
1248 void StatementImpl::AttachTransactionImpl(TransactionImpl* transaction)
\r
1250 if (transaction == 0)
\r
1251 throw LogicExceptionImpl("Statement::AttachTransaction",
\r
1252 _("Can't attach a 0 ITransaction object."));
\r
1254 if (mTransaction != 0) mTransaction->DetachStatementImpl(this);
\r
1255 mTransaction = transaction;
\r
1256 mTransaction->AttachStatementImpl(this);
\r
1259 void StatementImpl::DetachTransactionImpl()
\r
1261 if (mTransaction == 0) return;
\r
1264 mTransaction->DetachStatementImpl(this);
\r
1268 void StatementImpl::CursorFree()
\r
1270 if (mCursorOpened)
\r
1272 mCursorOpened = false;
\r
1276 (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_close);
\r
1277 if (status.Errors())
\r
1278 throw SQLExceptionImpl(status, "StatementImpl::CursorFree(DSQL_close)",
\r
1279 _("isc_dsql_free_statement failed."));
\r
1284 StatementImpl::StatementImpl(DatabaseImpl* database, TransactionImpl* transaction,
\r
1285 const std::string& sql)
\r
1286 : mRefCount(0), mHandle(0), mDatabase(0), mTransaction(0),
\r
1287 mInRow(0), mOutRow(0),
\r
1288 mResultSetAvailable(false), mCursorOpened(false), mType(IBPP::stUnknown)
\r
1290 AttachDatabaseImpl(database);
\r
1291 if (transaction != 0) AttachTransactionImpl(transaction);
\r
1292 if (! sql.empty()) Prepare(sql);
\r
1295 StatementImpl::~StatementImpl()
\r
1299 try { if (mTransaction != 0) mTransaction->DetachStatementImpl(this); }
\r
1301 try { if (mDatabase != 0) mDatabase->DetachStatementImpl(this); }
\r