backends/firebird/blob.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2004-2006 Maciej Sobczak, Stephen Hutton, Rafal Bobrowski
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 
8 #define SOCI_FIREBIRD_SOURCE
9 #include "soci-firebird.h"
10 #include "error-firebird.h"
11 
12 using namespace soci;
13 using namespace soci::details::firebird;
14 
16  : session_(session), from_db_(false), bhp_(0), loaded_(false),
17  max_seg_size_(0)
18 {}
19 
21 {
22  cleanUp();
23 }
24 
26 {
27  if (from_db_ && bhp_ == 0)
28  {
29  open();
30  }
31 
32  return data_.size();
33 }
34 
36  std::size_t offset, char * buf, std::size_t toRead)
37 {
38  if (from_db_ && (loaded_ == false))
39  {
40  // this is blob fetched from database, but not loaded yet
41  load();
42  }
43 
44  std::size_t size = data_.size();
45 
46  if (offset > size)
47  {
48  throw soci_error("Can't read past-the-end of BLOB data");
49  }
50 
51  char * itr = buf;
52  std::size_t limit = size - offset < toRead ? size - offset : toRead;
53  std::size_t index = 0;
54 
55  while (index < limit)
56  {
57  *itr = data_[offset+index];
58  ++index;
59  ++itr;
60  }
61 
62  return limit;
63 }
64 
65 std::size_t firebird_blob_backend::write(std::size_t offset, char const * buf,
66  std::size_t toWrite)
67 {
68  if (from_db_ && (loaded_ == false))
69  {
70  // this is blob fetched from database, but not loaded yet
71  load();
72  }
73 
74  std::size_t size = data_.size();
75 
76  if (offset > size)
77  {
78  throw soci_error("Can't write past-the-end of BLOB data");
79  }
80 
81  // make sure there is enough space in buffer
82  if (toWrite > (size - offset))
83  {
84  data_.resize(size + (toWrite - (size - offset)));
85  }
86 
87  writeBuffer(offset, buf, toWrite);
88 
89  return toWrite;
90 }
91 
93  char const * buf, std::size_t toWrite)
94 {
95  if (from_db_ && (loaded_ == false))
96  {
97  // this is blob fetched from database, but not loaded yet
98  load();
99  }
100 
101  std::size_t size = data_.size();
102  data_.resize(size + toWrite);
103 
104  writeBuffer(size, buf, toWrite);
105 
106  return toWrite;
107 }
108 
109 void firebird_blob_backend::trim(std::size_t newLen)
110 {
111  if (from_db_ && (loaded_ == false))
112  {
113  // this is blob fetched from database, but not loaded yet
114  load();
115  }
116 
117  data_.resize(newLen);
118 }
119 
120 void firebird_blob_backend::writeBuffer(std::size_t offset,
121  char const * buf, std::size_t toWrite)
122 {
123  char const * itr = buf;
124  char const * end_itr = buf + toWrite;
125 
126  while (itr!=end_itr)
127  {
128  data_[offset++] = *itr++;
129  }
130 }
131 
133 {
134  if (bhp_ != 0)
135  {
136  // BLOB already opened
137  return;
138  }
139 
140  ISC_STATUS stat[20];
141 
142  if (isc_open_blob2(stat, &session_.dbhp_, &session_.trhp_, &bhp_,
143  &bid_, 0, NULL))
144  {
145  bhp_ = 0L;
146  throw_iscerror(stat);
147  }
148 
149  // get basic blob info
150  long blob_size = getBLOBInfo();
151 
152  data_.resize(blob_size);
153 }
154 
156 {
157  from_db_ = false;
158  loaded_ = false;
159  max_seg_size_ = 0;
160  data_.resize(0);
161 
162  if (bhp_ != 0)
163  {
164  // close blob
165  ISC_STATUS stat[20];
166  if (isc_close_blob(stat, &bhp_))
167  {
168  throw_iscerror(stat);
169  }
170  bhp_ = 0;
171  }
172 }
173 
174 // loads blob data into internal buffer
176 {
177  if (bhp_ == 0)
178  {
179  open();
180  }
181 
182  ISC_STATUS stat[20];
183  unsigned short bytes;
184  std::vector<char>::size_type total_bytes = 0;
185  bool keep_reading = false;
186 
187  do
188  {
189  bytes = 0;
190  // next segment of data
191  // data_ is large-enough because we know total size of blob
192  isc_get_segment(stat, &bhp_, &bytes, static_cast<short>(max_seg_size_),
193  &data_[total_bytes]);
194 
195  total_bytes += bytes;
196 
197  if (total_bytes == data_.size())
198  {
199  // we have all BLOB data
200  keep_reading = false;
201  }
202  else if (stat[1] == 0 || stat[1] == isc_segment)
203  {
204  // there is more data to read from current segment (0)
205  // or there is next segment (isc_segment)
206  keep_reading = true;
207  }
208  else if (stat[1] == isc_segstr_eof)
209  {
210  // BLOB is shorter then we expected ???
211  keep_reading = false;
212  }
213  else
214  {
215  // an error has occured
216  throw_iscerror(stat);
217  }
218  }
219  while (keep_reading);
220 
221  loaded_ = true;
222 }
223 
224 // this method saves BLOB content to database
225 // (a new BLOB will be created at this point)
226 // BLOB will be closed after save.
228 {
229  // close old blob if necessary
230  ISC_STATUS stat[20];
231  if (bhp_ != 0)
232  {
233  if (isc_close_blob(stat, &bhp_))
234  {
235  throw_iscerror(stat);
236  }
237  bhp_ = 0;
238  }
239 
240  // create new blob
241  if (isc_create_blob(stat, &session_.dbhp_, &session_.trhp_,
242  &bhp_, &bid_))
243  {
244  throw_iscerror(stat);
245  }
246 
247  if (data_.size() > 0)
248  {
249  // write data
250  if (isc_put_segment(stat, &bhp_,
251  static_cast<unsigned short>(data_.size()), &data_[0]))
252  {
253  throw_iscerror(stat);
254  }
255  }
256 
257  cleanUp();
258  from_db_ = true;
259 }
260 
261 // retrives number of segments and total length of BLOB
262 // returns total length of BLOB
264 {
265  char blob_items[] = {isc_info_blob_max_segment, isc_info_blob_total_length};
266  char res_buffer[20], *p, item;
267  short length;
268  long total_length = 0;
269 
270  ISC_STATUS stat[20];
271 
272  if (isc_blob_info(stat, &bhp_, sizeof(blob_items), blob_items,
273  sizeof(res_buffer), res_buffer))
274  {
275  throw_iscerror(stat);
276  }
277 
278  for (p = res_buffer; *p != isc_info_end ;)
279  {
280  item = *p++;
281  length = static_cast<short>(isc_vax_integer(p, 2));
282  p += 2;
283  switch (item)
284  {
285  case isc_info_blob_max_segment:
286  max_seg_size_ = isc_vax_integer(p, length);
287  break;
288  case isc_info_blob_total_length:
289  total_length = isc_vax_integer(p, length);
290  break;
291  case isc_info_truncated:
292  throw soci_error("Fatal Error: BLOB info truncated!");
293  break;
294  default:
295  break;
296  }
297  p += length;
298  }
299 
300  return total_length;
301 }
std::vector< char > data_
virtual std::size_t append(char const *buf, std::size_t toWrite)
firebird_blob_backend(firebird_session_backend &session)
virtual void writeBuffer(std::size_t offset, char const *buf, std::size_t toWrite)
virtual std::size_t write(std::size_t offset, char const *buf, std::size_t toWrite)
firebird_session_backend & session_
void throw_iscerror(ISC_STATUS *status_vector)
virtual std::size_t read(std::size_t offset, char *buf, std::size_t toRead)
virtual void trim(std::size_t newLen)


asr_lib_ism
Author(s): Hanselmann Fabian, Heller Florian, Heizmann Heinrich, Kübler Marcel, Mehlhaus Jonas, Meißner Pascal, Qattan Mohamad, Reckling Reno, Stroh Daniel
autogenerated on Wed Jan 8 2020 04:02:40