00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #if defined(_MSC_VER)
00028 #pragma warning(disable: 4786 4996)
00029 #ifndef _DEBUG
00030 #pragma warning(disable: 4702)
00031 #endif
00032 #endif
00033
00034 #include "_ibpp.h"
00035
00036 #ifdef HAS_HDRSTOP
00037 #pragma hdrstop
00038 #endif
00039
00040 #include <algorithm>
00041
00042 using namespace ibpp_internals;
00043
00044
00045
00046 void DatabaseImpl::Create(int dialect)
00047 {
00048 if (mHandle != 0)
00049 throw LogicExceptionImpl("Database::Create", _("Database is already connected."));
00050 if (mDatabaseName.empty())
00051 throw LogicExceptionImpl("Database::Create", _("Unspecified database name."));
00052 if (mUserName.empty())
00053 throw LogicExceptionImpl("Database::Create", _("Unspecified user name."));
00054 if (dialect != 1 && dialect != 3)
00055 throw LogicExceptionImpl("Database::Create", _("Only dialects 1 and 3 are supported."));
00056
00057
00058 std::string create;
00059 create.assign("CREATE DATABASE '");
00060 if (! mServerName.empty()) create.append(mServerName).append(":");
00061 create.append(mDatabaseName).append("' ");
00062
00063 create.append("USER '").append(mUserName).append("' ");
00064 if (! mUserPassword.empty())
00065 create.append("PASSWORD '").append(mUserPassword).append("' ");
00066
00067 if (! mCreateParams.empty()) create.append(mCreateParams);
00068
00069
00070 isc_tr_handle tr_handle = 0;
00071 IBS status;
00072 (*gds.Call()->m_dsql_execute_immediate)(status.Self(), &mHandle, &tr_handle,
00073 0, const_cast<char*>(create.c_str()), short(dialect), NULL);
00074 if (status.Errors())
00075 throw SQLExceptionImpl(status, "Database::Create", _("isc_dsql_execute_immediate failed"));
00076
00077 Disconnect();
00078 }
00079
00080 void DatabaseImpl::Connect()
00081 {
00082 if (mHandle != 0) return;
00083
00084 if (mDatabaseName.empty())
00085 throw LogicExceptionImpl("Database::Connect", _("Unspecified database name."));
00086 if (mUserName.empty())
00087 throw LogicExceptionImpl("Database::Connect", _("Unspecified user name."));
00088
00089
00090 DPB dpb;
00091 dpb.Insert(isc_dpb_user_name, mUserName.c_str());
00092 dpb.Insert(isc_dpb_password, mUserPassword.c_str());
00093 if (! mRoleName.empty()) dpb.Insert(isc_dpb_sql_role_name, mRoleName.c_str());
00094 if (! mCharSet.empty()) dpb.Insert(isc_dpb_lc_ctype, mCharSet.c_str());
00095
00096 std::string connect;
00097 if (! mServerName.empty())
00098 connect.assign(mServerName).append(":");
00099 connect.append(mDatabaseName);
00100
00101 IBS status;
00102 (*gds.Call()->m_attach_database)(status.Self(), (short)connect.size(),
00103 const_cast<char*>(connect.c_str()), &mHandle, dpb.Size(), dpb.Self());
00104 if (status.Errors())
00105 {
00106 mHandle = 0;
00107 throw SQLExceptionImpl(status, "Database::Connect", _("isc_attach_database failed"));
00108 }
00109
00110
00111
00112
00113
00114
00115 char items[] = {isc_info_ods_version,
00116 isc_info_db_SQL_dialect,
00117 isc_info_end};
00118 RB result(100);
00119
00120 status.Reset();
00121 (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,
00122 result.Size(), result.Self());
00123 if (status.Errors())
00124 {
00125 status.Reset();
00126 (*gds.Call()->m_detach_database)(status.Self(), &mHandle);
00127 mHandle = 0;
00128 throw SQLExceptionImpl(status, "Database::Connect", _("isc_database_info failed"));
00129 }
00130
00131 int ODS = result.GetValue(isc_info_ods_version);
00132 if (ODS <= 9)
00133 {
00134 status.Reset();
00135 (*gds.Call()->m_detach_database)(status.Self(), &mHandle);
00136 mHandle = 0;
00137 throw LogicExceptionImpl("Database::Connect",
00138 _("Unsupported Server : wrong ODS version (%d), at least '10' required."), ODS);
00139 }
00140
00141 mDialect = result.GetValue(isc_info_db_SQL_dialect);
00142 if (mDialect != 1 && mDialect != 3)
00143 {
00144 status.Reset();
00145 (*gds.Call()->m_detach_database)(status.Self(), &mHandle);
00146 mHandle = 0;
00147 throw LogicExceptionImpl("Database::Connect", _("Dialect 1 or 3 required"));
00148 }
00149
00150
00151 if (ODS >= 10 && gds.Call()->mGDSVersion < 60)
00152 {
00153 status.Reset();
00154 (*gds.Call()->m_detach_database)(status.Self(), &mHandle);
00155 mHandle = 0;
00156 throw LogicExceptionImpl("Database::Connect", _("GDS32.DLL version 5 against IBSERVER 6"));
00157 }
00158 }
00159
00160 void DatabaseImpl::Inactivate()
00161 {
00162 if (mHandle == 0) return;
00163
00164
00165 for (unsigned i = 0; i < mTransactions.size(); i++)
00166 {
00167 if (mTransactions[i]->Started())
00168 mTransactions[i]->Rollback();
00169 }
00170
00171
00172 for (unsigned i = 0; i < mEvents.size(); i++)
00173 mEvents[i]->Clear();
00174
00175
00176 while (mBlobs.size() > 0)
00177 mBlobs.back()->DetachDatabaseImpl();
00178
00179
00180 while (mArrays.size() > 0)
00181 mArrays.back()->DetachDatabaseImpl();
00182
00183
00184 while (mStatements.size() > 0)
00185 mStatements.back()->DetachDatabaseImpl();
00186
00187
00188 while (mTransactions.size() > 0)
00189 mTransactions.back()->DetachDatabaseImpl(this);
00190
00191
00192 while (mEvents.size() > 0)
00193 mEvents.back()->DetachDatabaseImpl();
00194 }
00195
00196 void DatabaseImpl::Disconnect()
00197 {
00198 if (mHandle == 0) return;
00199
00200
00201 Inactivate();
00202
00203
00204 IBS status;
00205 (*gds.Call()->m_detach_database)(status.Self(), &mHandle);
00206
00207
00208
00209 mHandle = 0;
00210 if (status.Errors())
00211 throw SQLExceptionImpl(status, "Database::Disconnect", _("isc_detach_database failed"));
00212 }
00213
00214 void DatabaseImpl::Drop()
00215 {
00216 if (mHandle == 0)
00217 throw LogicExceptionImpl("Database::Drop", _("Database must be connected."));
00218
00219
00220 Inactivate();
00221
00222 IBS vector;
00223 (*gds.Call()->m_drop_database)(vector.Self(), &mHandle);
00224 if (vector.Errors())
00225 throw SQLExceptionImpl(vector, "Database::Drop", _("isc_drop_database failed"));
00226
00227 mHandle = 0;
00228 }
00229
00230 void DatabaseImpl::Info(int* ODSMajor, int* ODSMinor,
00231 int* PageSize, int* Pages, int* Buffers, int* Sweep,
00232 bool* Sync, bool* Reserve)
00233 {
00234 if (mHandle == 0)
00235 throw LogicExceptionImpl("Database::Info", _("Database is not connected."));
00236
00237 char items[] = {isc_info_ods_version,
00238 isc_info_ods_minor_version,
00239 isc_info_page_size,
00240 isc_info_allocation,
00241 isc_info_num_buffers,
00242 isc_info_sweep_interval,
00243 isc_info_forced_writes,
00244 isc_info_no_reserve,
00245 isc_info_end};
00246 IBS status;
00247 RB result(256);
00248
00249 status.Reset();
00250 (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,
00251 result.Size(), result.Self());
00252 if (status.Errors())
00253 throw SQLExceptionImpl(status, "Database::Info", _("isc_database_info failed"));
00254
00255 if (ODSMajor != 0) *ODSMajor = result.GetValue(isc_info_ods_version);
00256 if (ODSMinor != 0) *ODSMinor = result.GetValue(isc_info_ods_minor_version);
00257 if (PageSize != 0) *PageSize = result.GetValue(isc_info_page_size);
00258 if (Pages != 0) *Pages = result.GetValue(isc_info_allocation);
00259 if (Buffers != 0) *Buffers = result.GetValue(isc_info_num_buffers);
00260 if (Sweep != 0) *Sweep = result.GetValue(isc_info_sweep_interval);
00261 if (Sync != 0)
00262 *Sync = result.GetValue(isc_info_forced_writes) == 1 ? true : false;
00263 if (Reserve != 0)
00264 *Reserve = result.GetValue(isc_info_no_reserve) == 1 ? false : true;
00265 }
00266
00267 void DatabaseImpl::Statistics(int* Fetches, int* Marks, int* Reads, int* Writes)
00268 {
00269 if (mHandle == 0)
00270 throw LogicExceptionImpl("Database::Statistics", _("Database is not connected."));
00271
00272 char items[] = {isc_info_fetches,
00273 isc_info_marks,
00274 isc_info_reads,
00275 isc_info_writes,
00276 isc_info_end};
00277 IBS status;
00278 RB result(128);
00279
00280 status.Reset();
00281 (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,
00282 result.Size(), result.Self());
00283 if (status.Errors())
00284 throw SQLExceptionImpl(status, "Database::Statistics", _("isc_database_info failed"));
00285
00286 if (Fetches != 0) *Fetches = result.GetValue(isc_info_fetches);
00287 if (Marks != 0) *Marks = result.GetValue(isc_info_marks);
00288 if (Reads != 0) *Reads = result.GetValue(isc_info_reads);
00289 if (Writes != 0) *Writes = result.GetValue(isc_info_writes);
00290 }
00291
00292 void DatabaseImpl::Counts(int* Insert, int* Update, int* Delete,
00293 int* ReadIdx, int* ReadSeq)
00294 {
00295 if (mHandle == 0)
00296 throw LogicExceptionImpl("Database::Counts", _("Database is not connected."));
00297
00298 char items[] = {isc_info_insert_count,
00299 isc_info_update_count,
00300 isc_info_delete_count,
00301 isc_info_read_idx_count,
00302 isc_info_read_seq_count,
00303 isc_info_end};
00304 IBS status;
00305 RB result(1024);
00306
00307 status.Reset();
00308 (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,
00309 result.Size(), result.Self());
00310 if (status.Errors())
00311 throw SQLExceptionImpl(status, "Database::Counts", _("isc_database_info failed"));
00312
00313 if (Insert != 0) *Insert = result.GetCountValue(isc_info_insert_count);
00314 if (Update != 0) *Update = result.GetCountValue(isc_info_update_count);
00315 if (Delete != 0) *Delete = result.GetCountValue(isc_info_delete_count);
00316 if (ReadIdx != 0) *ReadIdx = result.GetCountValue(isc_info_read_idx_count);
00317 if (ReadSeq != 0) *ReadSeq = result.GetCountValue(isc_info_read_seq_count);
00318 }
00319
00320 void DatabaseImpl::Users(std::vector<std::string>& users)
00321 {
00322 if (mHandle == 0)
00323 throw LogicExceptionImpl("Database::Users", _("Database is not connected."));
00324
00325 char items[] = {isc_info_user_names,
00326 isc_info_end};
00327 IBS status;
00328 RB result(8000);
00329
00330 status.Reset();
00331 (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items,
00332 result.Size(), result.Self());
00333 if (status.Errors())
00334 {
00335 status.Reset();
00336 throw SQLExceptionImpl(status, "Database::Users", _("isc_database_info failed"));
00337 }
00338
00339 users.clear();
00340 char* p = result.Self();
00341 while (*p == isc_info_user_names)
00342 {
00343 p += 3;
00344 int len = (int)(*p);
00345 ++p;
00346 if (len != 0) users.push_back(std::string().append(p, len));
00347 p += len;
00348 }
00349 return;
00350 }
00351
00352 IBPP::IDatabase* DatabaseImpl::AddRef()
00353 {
00354 ASSERTION(mRefCount >= 0);
00355 ++mRefCount;
00356 return this;
00357 }
00358
00359 void DatabaseImpl::Release()
00360 {
00361
00362 ASSERTION(mRefCount >= 0);
00363 --mRefCount;
00364 try { if (mRefCount <= 0) delete this; }
00365 catch (...) { }
00366 }
00367
00368
00369
00370 void DatabaseImpl::AttachTransactionImpl(TransactionImpl* tr)
00371 {
00372 if (tr == 0)
00373 throw LogicExceptionImpl("Database::AttachTransaction",
00374 _("Transaction object is null."));
00375
00376 mTransactions.push_back(tr);
00377 }
00378
00379 void DatabaseImpl::DetachTransactionImpl(TransactionImpl* tr)
00380 {
00381 if (tr == 0)
00382 throw LogicExceptionImpl("Database::DetachTransaction",
00383 _("ITransaction object is null."));
00384
00385 mTransactions.erase(std::find(mTransactions.begin(), mTransactions.end(), tr));
00386 }
00387
00388 void DatabaseImpl::AttachStatementImpl(StatementImpl* st)
00389 {
00390 if (st == 0)
00391 throw LogicExceptionImpl("Database::AttachStatement",
00392 _("Can't attach a null Statement object."));
00393
00394 mStatements.push_back(st);
00395 }
00396
00397 void DatabaseImpl::DetachStatementImpl(StatementImpl* st)
00398 {
00399 if (st == 0)
00400 throw LogicExceptionImpl("Database::DetachStatement",
00401 _("Can't detach a null Statement object."));
00402
00403 mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st));
00404 }
00405
00406 void DatabaseImpl::AttachBlobImpl(BlobImpl* bb)
00407 {
00408 if (bb == 0)
00409 throw LogicExceptionImpl("Database::AttachBlob",
00410 _("Can't attach a null Blob object."));
00411
00412 mBlobs.push_back(bb);
00413 }
00414
00415 void DatabaseImpl::DetachBlobImpl(BlobImpl* bb)
00416 {
00417 if (bb == 0)
00418 throw LogicExceptionImpl("Database::DetachBlob",
00419 _("Can't detach a null Blob object."));
00420
00421 mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb));
00422 }
00423
00424 void DatabaseImpl::AttachArrayImpl(ArrayImpl* ar)
00425 {
00426 if (ar == 0)
00427 throw LogicExceptionImpl("Database::AttachArray",
00428 _("Can't attach a null Array object."));
00429
00430 mArrays.push_back(ar);
00431 }
00432
00433 void DatabaseImpl::DetachArrayImpl(ArrayImpl* ar)
00434 {
00435 if (ar == 0)
00436 throw LogicExceptionImpl("Database::DetachArray",
00437 _("Can't detach a null Array object."));
00438
00439 mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar));
00440 }
00441
00442 void DatabaseImpl::AttachEventsImpl(EventsImpl* ev)
00443 {
00444 if (ev == 0)
00445 throw LogicExceptionImpl("Database::AttachEventsImpl",
00446 _("Can't attach a null Events object."));
00447
00448 mEvents.push_back(ev);
00449 }
00450
00451 void DatabaseImpl::DetachEventsImpl(EventsImpl* ev)
00452 {
00453 if (ev == 0)
00454 throw LogicExceptionImpl("Database::DetachEventsImpl",
00455 _("Can't detach a null Events object."));
00456
00457 mEvents.erase(std::find(mEvents.begin(), mEvents.end(), ev));
00458 }
00459
00460 DatabaseImpl::DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName,
00461 const std::string& UserName, const std::string& UserPassword,
00462 const std::string& RoleName, const std::string& CharSet,
00463 const std::string& CreateParams) :
00464
00465 mRefCount(0), mHandle(0),
00466 mServerName(ServerName), mDatabaseName(DatabaseName),
00467 mUserName(UserName), mUserPassword(UserPassword), mRoleName(RoleName),
00468 mCharSet(CharSet), mCreateParams(CreateParams),
00469 mDialect(3)
00470 {
00471 }
00472
00473 DatabaseImpl::~DatabaseImpl()
00474 {
00475 try { if (Connected()) Disconnect(); }
00476 catch(...) { }
00477 }
00478
00479
00480
00481