1 ///////////////////////////////////////////////////////////////////////////////
\r
3 // File : $Id: blob.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $
\r
4 // Subject : IBPP, Blob 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 BlobImpl::Open()
\r
49 throw LogicExceptionImpl("Blob::Open", _("Blob already opened."));
\r
51 throw LogicExceptionImpl("Blob::Open", _("No Database is attached."));
\r
52 if (mTransaction == 0)
\r
53 throw LogicExceptionImpl("Blob::Open", _("No Transaction is attached."));
\r
55 throw LogicExceptionImpl("Blob::Open", _("Blob Id is not assigned."));
\r
58 (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),
\r
59 mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);
\r
60 if (status.Errors())
\r
61 throw SQLExceptionImpl(status, "Blob::Open", _("isc_open_blob2 failed."));
\r
65 void BlobImpl::Create()
\r
68 throw LogicExceptionImpl("Blob::Create", _("Blob already opened."));
\r
70 throw LogicExceptionImpl("Blob::Create", _("No Database is attached."));
\r
71 if (mTransaction == 0)
\r
72 throw LogicExceptionImpl("Blob::Create", _("No Transaction is attached."));
\r
75 (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),
\r
76 mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);
\r
77 if (status.Errors())
\r
78 throw SQLExceptionImpl(status, "Blob::Create",
\r
79 _("isc_create_blob failed."));
\r
84 void BlobImpl::Close()
\r
86 if (mHandle == 0) return; // Not opened anyway
\r
89 (*gds.Call()->m_close_blob)(status.Self(), &mHandle);
\r
90 if (status.Errors())
\r
91 throw SQLExceptionImpl(status, "Blob::Close", _("isc_close_blob failed."));
\r
95 void BlobImpl::Cancel()
\r
97 if (mHandle == 0) return; // Not opened anyway
\r
100 throw LogicExceptionImpl("Blob::Cancel", _("Can't cancel a Blob opened for read"));
\r
103 (*gds.Call()->m_cancel_blob)(status.Self(), &mHandle);
\r
104 if (status.Errors())
\r
105 throw SQLExceptionImpl(status, "Blob::Cancel", _("isc_cancel_blob failed."));
\r
107 mIdAssigned = false;
\r
110 int BlobImpl::Read(void* buffer, int size)
\r
113 throw LogicExceptionImpl("Blob::Read", _("The Blob is not opened"));
\r
115 throw LogicExceptionImpl("Blob::Read", _("Can't read from Blob opened for write"));
\r
116 if (size < 1 || size > (64*1024-1))
\r
117 throw LogicExceptionImpl("Blob::Read", _("Invalid segment size (max 64Kb-1)"));
\r
120 unsigned short bytesread;
\r
121 int result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, &bytesread,
\r
122 (unsigned short)size, (char*)buffer);
\r
123 if (result == isc_segstr_eof) return 0; // Fin du blob
\r
124 if (result != isc_segment && status.Errors())
\r
125 throw SQLExceptionImpl(status, "Blob::Read", _("isc_get_segment failed."));
\r
126 return (int)bytesread;
\r
129 void BlobImpl::Write(const void* buffer, int size)
\r
132 throw LogicExceptionImpl("Blob::Write", _("The Blob is not opened"));
\r
134 throw LogicExceptionImpl("Blob::Write", _("Can't write to Blob opened for read"));
\r
135 if (size < 1 || size > (64*1024-1))
\r
136 throw LogicExceptionImpl("Blob::Write", _("Invalid segment size (max 64Kb-1)"));
\r
139 (*gds.Call()->m_put_segment)(status.Self(), &mHandle,
\r
140 (unsigned short)size, (char*)buffer);
\r
141 if (status.Errors())
\r
142 throw SQLExceptionImpl(status, "Blob::Write", _("isc_put_segment failed."));
\r
145 void BlobImpl::Info(int* Size, int* Largest, int* Segments)
\r
147 char items[] = {isc_info_blob_total_length,
\r
148 isc_info_blob_max_segment,
\r
149 isc_info_blob_num_segments};
\r
152 throw LogicExceptionImpl("Blob::GetInfo", _("The Blob is not opened"));
\r
156 (*gds.Call()->m_blob_info)(status.Self(), &mHandle, sizeof(items), items,
\r
157 (short)result.Size(), result.Self());
\r
158 if (status.Errors())
\r
159 throw SQLExceptionImpl(status, "Blob::GetInfo", _("isc_blob_info failed."));
\r
161 if (Size != 0) *Size = result.GetValue(isc_info_blob_total_length);
\r
162 if (Largest != 0) *Largest = result.GetValue(isc_info_blob_max_segment);
\r
163 if (Segments != 0) *Segments = result.GetValue(isc_info_blob_num_segments);
\r
166 void BlobImpl::Save(const std::string& data)
\r
169 throw LogicExceptionImpl("Blob::Save", _("Blob already opened."));
\r
170 if (mDatabase == 0)
\r
171 throw LogicExceptionImpl("Blob::Save", _("No Database is attached."));
\r
172 if (mTransaction == 0)
\r
173 throw LogicExceptionImpl("Blob::Save", _("No Transaction is attached."));
\r
176 (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(),
\r
177 mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);
\r
178 if (status.Errors())
\r
179 throw SQLExceptionImpl(status, "Blob::Save",
\r
180 _("isc_create_blob failed."));
\r
181 mIdAssigned = true;
\r
185 size_t len = data.size();
\r
188 size_t blklen = (len < 32*1024-1) ? len : 32*1024-1;
\r
190 (*gds.Call()->m_put_segment)(status.Self(), &mHandle,
\r
191 (unsigned short)blklen, const_cast<char*>(data.data()+pos));
\r
192 if (status.Errors())
\r
193 throw SQLExceptionImpl(status, "Blob::Save",
\r
194 _("isc_put_segment failed."));
\r
200 (*gds.Call()->m_close_blob)(status.Self(), &mHandle);
\r
201 if (status.Errors())
\r
202 throw SQLExceptionImpl(status, "Blob::Save", _("isc_close_blob failed."));
\r
206 void BlobImpl::Load(std::string& data)
\r
209 throw LogicExceptionImpl("Blob::Load", _("Blob already opened."));
\r
210 if (mDatabase == 0)
\r
211 throw LogicExceptionImpl("Blob::Load", _("No Database is attached."));
\r
212 if (mTransaction == 0)
\r
213 throw LogicExceptionImpl("Blob::Load", _("No Transaction is attached."));
\r
215 throw LogicExceptionImpl("Blob::Load", _("Blob Id is not assigned."));
\r
218 (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(),
\r
219 mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0);
\r
220 if (status.Errors())
\r
221 throw SQLExceptionImpl(status, "Blob::Load", _("isc_open_blob2 failed."));
\r
222 mWriteMode = false;
\r
224 size_t blklen = 32*1024-1;
\r
225 data.resize(blklen);
\r
232 unsigned short bytesread;
\r
233 int result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle,
\r
234 &bytesread, (unsigned short)blklen,
\r
235 const_cast<char*>(data.data()+pos));
\r
236 if (result == isc_segstr_eof) break; // End of blob
\r
237 if (result != isc_segment && status.Errors())
\r
238 throw SQLExceptionImpl(status, "Blob::Load", _("isc_get_segment failed."));
\r
242 data.resize(size + blklen);
\r
247 (*gds.Call()->m_close_blob)(status.Self(), &mHandle);
\r
248 if (status.Errors())
\r
249 throw SQLExceptionImpl(status, "Blob::Load", _("isc_close_blob failed."));
\r
253 IBPP::Database BlobImpl::DatabasePtr() const
\r
255 if (mDatabase == 0) throw LogicExceptionImpl("Blob::DatabasePtr",
\r
256 _("No Database is attached."));
\r
260 IBPP::Transaction BlobImpl::TransactionPtr() const
\r
262 if (mTransaction == 0) throw LogicExceptionImpl("Blob::TransactionPtr",
\r
263 _("No Transaction is attached."));
\r
264 return mTransaction;
\r
267 IBPP::IBlob* BlobImpl::AddRef()
\r
269 ASSERTION(mRefCount >= 0);
\r
274 void BlobImpl::Release()
\r
276 // Release cannot throw, except in DEBUG builds on assertion
\r
277 ASSERTION(mRefCount >= 0);
\r
279 try { if (mRefCount <= 0) delete this; }
\r
283 // (((((((( OBJECT INTERNAL METHODS ))))))))
\r
285 void BlobImpl::Init()
\r
287 mIdAssigned = false;
\r
288 mWriteMode = false;
\r
294 void BlobImpl::SetId(ISC_QUAD* quad)
\r
297 throw LogicExceptionImpl("BlobImpl::SetId", _("Can't set Id on an opened BlobImpl."));
\r
299 throw LogicExceptionImpl("BlobImpl::SetId", _("Null Id reference detected."));
\r
301 memcpy(&mId, quad, sizeof(mId));
\r
302 mIdAssigned = true;
\r
305 void BlobImpl::GetId(ISC_QUAD* quad)
\r
308 throw LogicExceptionImpl("BlobImpl::GetId", _("Can't get Id on an opened BlobImpl."));
\r
310 throw LogicExceptionImpl("BlobImpl::GetId", _("Can only get Id of a newly created Blob."));
\r
312 throw LogicExceptionImpl("BlobImpl::GetId", _("Null Id reference detected."));
\r
314 memcpy(quad, &mId, sizeof(mId));
\r
317 void BlobImpl::AttachDatabaseImpl(DatabaseImpl* database)
\r
319 if (database == 0) throw LogicExceptionImpl("Blob::AttachDatabase",
\r
320 _("Can't attach a NULL Database object."));
\r
322 if (mDatabase != 0) mDatabase->DetachBlobImpl(this);
\r
323 mDatabase = database;
\r
324 mDatabase->AttachBlobImpl(this);
\r
327 void BlobImpl::AttachTransactionImpl(TransactionImpl* transaction)
\r
329 if (transaction == 0) throw LogicExceptionImpl("Blob::AttachTransaction",
\r
330 _("Can't attach a NULL Transaction object."));
\r
332 if (mTransaction != 0) mTransaction->DetachBlobImpl(this);
\r
333 mTransaction = transaction;
\r
334 mTransaction->AttachBlobImpl(this);
\r
337 void BlobImpl::DetachDatabaseImpl()
\r
339 if (mDatabase == 0) return;
\r
341 mDatabase->DetachBlobImpl(this);
\r
345 void BlobImpl::DetachTransactionImpl()
\r
347 if (mTransaction == 0) return;
\r
349 mTransaction->DetachBlobImpl(this);
\r
353 BlobImpl::BlobImpl(DatabaseImpl* database, TransactionImpl* transaction)
\r
357 AttachDatabaseImpl(database);
\r
358 if (transaction != 0) AttachTransactionImpl(transaction);
\r
361 BlobImpl::~BlobImpl()
\r
367 if (mWriteMode) Cancel();
\r
373 try { if (mTransaction != 0) mTransaction->DetachBlobImpl(this); }
\r
375 try { if (mDatabase != 0) mDatabase->DetachBlobImpl(this); }
\r