Line data Source code
1 : // Copyright (c) 2019 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdatabase
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 :
21 : /** \file
22 : * \brief Database file implementation.
23 : *
24 : * Each table uses one or more files. Each file is handled by a dbfile
25 : * object and a corresponding set of blocks.
26 : */
27 :
28 : // self
29 : //
30 : #include "snapdatabase/database/row.h"
31 :
32 :
33 : // last include
34 : //
35 : #include <snapdev/poison.h>
36 :
37 :
38 :
39 : namespace snapdatabase
40 : {
41 :
42 :
43 :
44 0 : row::row(table::pointer_t t)
45 0 : : f_table(t)
46 : {
47 0 : }
48 :
49 :
50 0 : buffer_t row::to_binary() const
51 : {
52 0 : buffer_t result;
53 :
54 0 : auto push_uint8 = [&](uint8_t value)
55 : {
56 0 : result.push_back(value);
57 0 : };
58 :
59 0 : auto push_uint16 = [&](uint16_t value)
60 : {
61 0 : result.push_back(value >> 0);
62 0 : result.push_back(value >> 8);
63 0 : };
64 :
65 0 : auto push_uint32 = [&](uint32_t value)
66 : {
67 0 : result.push_back(value);
68 0 : };
69 :
70 0 : auto push_uint64 = [&](uint64_t value)
71 : {
72 0 : result.push_back(value);
73 0 : };
74 :
75 0 : table::pointer_t t(f_table.lock());
76 0 : schema_column::map_by_id_t columns(t->columns_by_id());
77 :
78 0 : for(auto const & c : f_cells)
79 : {
80 0 : schema_column::pointer_t schema(c.second->schema());
81 :
82 0 : column_id_t const id(schema->column_id());
83 0 : push_uint16(id);
84 :
85 0 : switch(schema->type())
86 : {
87 0 : case struct_type_t::STRUCT_TYPE_VOID:
88 0 : snap::NOTUSED(c.second->is_void());
89 0 : break;
90 :
91 0 : case struct_type_t::STRUCT_TYPE_BITS8:
92 : case struct_type_t::STRUCT_TYPE_UINT8:
93 0 : push_uint8(c.second->get_uint8());
94 0 : break;
95 :
96 0 : case struct_type_t::STRUCT_TYPE_INT8:
97 0 : push_uint8(c.second->get_int8());
98 0 : break;
99 :
100 0 : case struct_type_t::STRUCT_TYPE_BITS16:
101 : case struct_type_t::STRUCT_TYPE_UINT16:
102 0 : push_uint16(c.second->get_uint16());
103 0 : break;
104 :
105 0 : case struct_type_t::STRUCT_TYPE_INT16:
106 0 : push_uint16(c.second->get_int16());
107 0 : break;
108 :
109 0 : case struct_type_t::STRUCT_TYPE_BITS32:
110 : case struct_type_t::STRUCT_TYPE_UINT32:
111 : case struct_type_t::STRUCT_TYPE_VERSION:
112 0 : push_uint32(c.second->get_uint32());
113 0 : break;
114 :
115 0 : case struct_type_t::STRUCT_TYPE_INT32:
116 0 : push_uint32(c.second->get_int32());
117 0 : break;
118 :
119 0 : case struct_type_t::STRUCT_TYPE_BITS64:
120 : case struct_type_t::STRUCT_TYPE_UINT64:
121 : case struct_type_t::STRUCT_TYPE_REFERENCE:
122 : case struct_type_t::STRUCT_TYPE_OID:
123 : case struct_type_t::STRUCT_TYPE_TIME:
124 : case struct_type_t::STRUCT_TYPE_MSTIME:
125 : case struct_type_t::STRUCT_TYPE_USTIME:
126 0 : push_uint64(c.second->get_uint64());
127 0 : break;
128 :
129 0 : case struct_type_t::STRUCT_TYPE_INT64:
130 0 : push_uint64(c.second->get_int64());
131 0 : break;
132 :
133 0 : case struct_type_t::STRUCT_TYPE_BITS128:
134 : case struct_type_t::STRUCT_TYPE_UINT128:
135 : {
136 0 : uint512_t const value(c.second->get_uint128());
137 0 : push_uint64(value.f_value[0]);
138 0 : push_uint64(value.f_value[1]);
139 : }
140 0 : break;
141 :
142 0 : case struct_type_t::STRUCT_TYPE_INT128:
143 : {
144 0 : int512_t const value(c.second->get_int128());
145 0 : push_uint64(value.f_value[0]);
146 0 : push_uint64(value.f_value[1]);
147 : }
148 0 : break;
149 :
150 0 : case struct_type_t::STRUCT_TYPE_BITS256:
151 : case struct_type_t::STRUCT_TYPE_UINT256:
152 : {
153 0 : uint512_t const value(c.second->get_uint256());
154 0 : push_uint64(value.f_value[0]);
155 0 : push_uint64(value.f_value[1]);
156 0 : push_uint64(value.f_value[2]);
157 0 : push_uint64(value.f_value[3]);
158 : }
159 0 : break;
160 :
161 0 : case struct_type_t::STRUCT_TYPE_INT256:
162 : {
163 0 : int512_t const value(c.second->get_int256());
164 0 : push_uint64(value.f_value[0]);
165 0 : push_uint64(value.f_value[1]);
166 0 : push_uint64(value.f_value[2]);
167 0 : push_uint64(value.f_value[3]);
168 : }
169 0 : break;
170 :
171 0 : case struct_type_t::STRUCT_TYPE_BITS512:
172 : case struct_type_t::STRUCT_TYPE_UINT512:
173 : {
174 0 : uint512_t const value(c.second->get_uint512());
175 0 : push_uint64(value.f_value[0]);
176 0 : push_uint64(value.f_value[1]);
177 0 : push_uint64(value.f_value[2]);
178 0 : push_uint64(value.f_value[3]);
179 0 : push_uint64(value.f_value[4]);
180 0 : push_uint64(value.f_value[5]);
181 0 : push_uint64(value.f_value[6]);
182 0 : push_uint64(value.f_value[7]);
183 : }
184 0 : break;
185 :
186 0 : case struct_type_t::STRUCT_TYPE_INT512:
187 : {
188 0 : int512_t const value(c.second->get_int512());
189 0 : push_uint64(value.f_value[0]);
190 0 : push_uint64(value.f_value[1]);
191 0 : push_uint64(value.f_value[2]);
192 0 : push_uint64(value.f_value[3]);
193 0 : push_uint64(value.f_value[4]);
194 0 : push_uint64(value.f_value[5]);
195 0 : push_uint64(value.f_value[6]);
196 0 : push_uint64(value.f_value[7]);
197 : }
198 0 : break;
199 :
200 0 : case struct_type_t::STRUCT_TYPE_FLOAT32:
201 : {
202 : union fi {
203 : uint32_t f_int = 0;
204 : float f_float;
205 : };
206 0 : fi value;
207 0 : value.f_float = c.second->get_float32();
208 0 : push_uint32(value.f_int);
209 : }
210 0 : break;
211 :
212 0 : case struct_type_t::STRUCT_TYPE_FLOAT64:
213 : {
214 : union fi {
215 : uint64_t f_int = 0;
216 : double f_float;
217 : };
218 0 : fi value;
219 0 : value.f_float = c.second->get_float64();
220 0 : push_uint64(value.f_int);
221 : }
222 0 : break;
223 :
224 0 : case struct_type_t::STRUCT_TYPE_FLOAT128:
225 : {
226 : union fi {
227 : uint64_t f_int[2] = { 0, 0 };
228 : long double f_float;
229 : };
230 0 : fi value;
231 0 : value.f_float = c.second->get_float128();
232 0 : push_uint64(value.f_int[0]);
233 0 : push_uint64(value.f_int[1]);
234 : }
235 0 : break;
236 :
237 0 : case struct_type_t::STRUCT_TYPE_P8STRING:
238 : {
239 0 : std::string const value(c.second->get_string());
240 0 : if(value.length() > 255)
241 : {
242 : throw out_of_bounds(
243 : "string to long for a P8STRING (max: 255, actually: "
244 0 : + std::to_string(value.length())
245 0 : + ").");
246 : }
247 0 : push_uint8(value.length());
248 0 : if(!value.empty())
249 : {
250 0 : uint8_t const * s(reinterpret_cast<uint8_t const *>(value.c_str()));
251 0 : result.insert(result.end(), s, s + value.length());
252 0 : }
253 : }
254 0 : break;
255 :
256 0 : case struct_type_t::STRUCT_TYPE_P16STRING:
257 : {
258 0 : std::string const value(c.second->get_string());
259 0 : if(value.length() > 65535)
260 : {
261 : throw out_of_bounds(
262 : "string to long for a P16STRING (max: 64Kb, actually: "
263 0 : + std::to_string(value.length())
264 0 : + ").");
265 : }
266 0 : uint16_t const size(static_cast<uint16_t>(value.length()));
267 0 : push_uint16(size);
268 0 : if(size > 0)
269 : {
270 0 : uint8_t const * s(reinterpret_cast<uint8_t const *>(value.c_str()));
271 0 : result.insert(result.end(), s, s + size);
272 0 : }
273 : }
274 0 : break;
275 :
276 0 : case struct_type_t::STRUCT_TYPE_P32STRING:
277 : {
278 0 : std::string const value(c.second->get_string());
279 0 : if(value.length() > 65535)
280 : {
281 : throw out_of_bounds(
282 : "string to long for a P32STRING (max: 4Gb, actually: "
283 0 : + std::to_string(value.length())
284 0 : + ").");
285 : }
286 0 : uint32_t const size(static_cast<uint32_t>(value.length()));
287 0 : push_uint32(size);
288 0 : if(size > 0)
289 : {
290 0 : uint8_t const * s(reinterpret_cast<uint8_t const *>(value.c_str()));
291 0 : result.insert(result.end(), s, s + size);
292 0 : }
293 : }
294 0 : break;
295 :
296 0 : case struct_type_t::STRUCT_TYPE_STRUCTURE:
297 : case struct_type_t::STRUCT_TYPE_ARRAY8:
298 : case struct_type_t::STRUCT_TYPE_ARRAY16:
299 : case struct_type_t::STRUCT_TYPE_ARRAY32:
300 : case struct_type_t::STRUCT_TYPE_BUFFER8:
301 : case struct_type_t::STRUCT_TYPE_BUFFER16:
302 : case struct_type_t::STRUCT_TYPE_BUFFER32:
303 : case struct_type_t::STRUCT_TYPE_END:
304 : case struct_type_t::STRUCT_TYPE_RENAMED:
305 : throw type_mismatch(
306 : "Unexpected type ("
307 0 : + std::to_string(static_cast<int>(schema->type()))
308 0 : + ") to convert a cell from binary.");
309 :
310 : }
311 : }
312 :
313 0 : return result;
314 : }
315 :
316 :
317 0 : void row::from_binary(buffer_t const & blob)
318 : {
319 0 : table::pointer_t t(f_table.lock());
320 0 : schema_column::map_by_id_t columns(t->columns_by_id());
321 0 : size_t pos(0);
322 :
323 0 : auto get_uint8 = [&]()
324 : {
325 0 : if(pos + 1 > blob.size())
326 : {
327 0 : throw unexpected_eof("blob too small for a [u]int8_t.");
328 : }
329 :
330 0 : uint8_t const value(blob[pos]);
331 0 : pos += 1;
332 0 : return value;
333 0 : };
334 :
335 0 : auto get_uint16 = [&]()
336 : {
337 0 : if(pos + 2 > blob.size())
338 : {
339 0 : throw unexpected_eof("blob too small for a [u]int16_t.");
340 : }
341 :
342 0 : uint16_t const value((static_cast<uint16_t>(blob[pos + 0]) << 0)
343 0 : + (static_cast<uint16_t>(blob[pos + 1]) << 8));
344 0 : pos += 2;
345 0 : return value;
346 0 : };
347 :
348 0 : auto get_uint32 = [&]()
349 : {
350 0 : if(pos + 4 > blob.size())
351 : {
352 0 : throw unexpected_eof("blob too small for a [u]int32_t.");
353 : }
354 :
355 0 : uint32_t const value((static_cast<uint32_t>(blob[pos + 0]) << 0)
356 0 : + (static_cast<uint32_t>(blob[pos + 1]) << 8)
357 0 : + (static_cast<uint32_t>(blob[pos + 2]) << 16)
358 0 : + (static_cast<uint32_t>(blob[pos + 3]) << 24));
359 0 : pos += 4;
360 0 : return value;
361 0 : };
362 :
363 0 : auto get_uint64 = [&]()
364 : {
365 0 : if(pos + 8 > blob.size())
366 : {
367 0 : throw unexpected_eof("blob too small for a [u]int64_t.");
368 : }
369 :
370 0 : uint64_t const value((static_cast<uint64_t>(blob[pos + 0]) << 0)
371 0 : + (static_cast<uint64_t>(blob[pos + 1]) << 8)
372 0 : + (static_cast<uint64_t>(blob[pos + 2]) << 16)
373 0 : + (static_cast<uint64_t>(blob[pos + 3]) << 24)
374 0 : + (static_cast<uint64_t>(blob[pos + 4]) << 32)
375 0 : + (static_cast<uint64_t>(blob[pos + 5]) << 40)
376 0 : + (static_cast<uint64_t>(blob[pos + 6]) << 48)
377 0 : + (static_cast<uint64_t>(blob[pos + 7]) << 56));
378 0 : pos += 8;
379 0 : return value;
380 0 : };
381 :
382 0 : while(pos < blob.size())
383 : {
384 0 : column_id_t const id(get_uint16());
385 0 : auto it(columns.find(id));
386 0 : if(it == columns.end())
387 : {
388 : throw column_not_found(
389 : "column with identifier "
390 0 : + std::to_string(static_cast<int>(id))
391 0 : + " not found.");
392 : }
393 :
394 0 : cell::pointer_t v(std::make_shared<cell>(it->second));
395 0 : switch(it->second->type())
396 : {
397 0 : case struct_type_t::STRUCT_TYPE_VOID:
398 0 : v->set_void();
399 0 : break;
400 :
401 0 : case struct_type_t::STRUCT_TYPE_BITS8:
402 : case struct_type_t::STRUCT_TYPE_UINT8:
403 0 : v->set_uint8(get_uint8());
404 0 : break;
405 :
406 0 : case struct_type_t::STRUCT_TYPE_INT8:
407 0 : v->set_int8(get_uint8());
408 0 : break;
409 :
410 0 : case struct_type_t::STRUCT_TYPE_BITS16:
411 : case struct_type_t::STRUCT_TYPE_UINT16:
412 0 : v->set_uint16(get_uint16());
413 0 : break;
414 :
415 0 : case struct_type_t::STRUCT_TYPE_INT16:
416 0 : v->set_int16(get_uint16());
417 0 : break;
418 :
419 0 : case struct_type_t::STRUCT_TYPE_BITS32:
420 : case struct_type_t::STRUCT_TYPE_UINT32:
421 : case struct_type_t::STRUCT_TYPE_VERSION:
422 0 : v->set_uint32(get_uint32());
423 0 : break;
424 :
425 0 : case struct_type_t::STRUCT_TYPE_INT32:
426 0 : v->set_int32(get_uint32());
427 0 : break;
428 :
429 0 : case struct_type_t::STRUCT_TYPE_BITS64:
430 : case struct_type_t::STRUCT_TYPE_UINT64:
431 : case struct_type_t::STRUCT_TYPE_REFERENCE:
432 : case struct_type_t::STRUCT_TYPE_OID:
433 : case struct_type_t::STRUCT_TYPE_TIME:
434 : case struct_type_t::STRUCT_TYPE_MSTIME:
435 : case struct_type_t::STRUCT_TYPE_USTIME:
436 0 : v->set_uint64(get_uint64());
437 0 : break;
438 :
439 0 : case struct_type_t::STRUCT_TYPE_INT64:
440 0 : v->set_int64(get_uint64());
441 0 : break;
442 :
443 0 : case struct_type_t::STRUCT_TYPE_BITS128:
444 : case struct_type_t::STRUCT_TYPE_UINT128:
445 : {
446 0 : uint512_t value;
447 0 : value.f_value[0] = get_uint64();
448 0 : value.f_value[1] = get_uint64();
449 0 : v->set_uint128(value);
450 : }
451 0 : break;
452 :
453 0 : case struct_type_t::STRUCT_TYPE_INT128:
454 : {
455 0 : int512_t value;
456 0 : value.f_value[0] = get_uint64();
457 0 : value.f_value[1] = get_uint64();
458 0 : value.f_value[2] = static_cast<int64_t>(value.f_value[1]) < 0 ? -1 : 0;
459 0 : value.f_value[3] = value.f_value[2];
460 0 : value.f_value[4] = value.f_value[2];
461 0 : value.f_value[5] = value.f_value[2];
462 0 : value.f_value[6] = value.f_value[2];
463 0 : value.f_high_value = value.f_value[2];
464 0 : v->set_int128(value);
465 : }
466 0 : break;
467 :
468 0 : case struct_type_t::STRUCT_TYPE_BITS256:
469 : case struct_type_t::STRUCT_TYPE_UINT256:
470 : {
471 0 : uint512_t value;
472 0 : value.f_value[0] = get_uint64();
473 0 : value.f_value[1] = get_uint64();
474 0 : value.f_value[2] = get_uint64();
475 0 : value.f_value[3] = get_uint64();
476 0 : v->set_uint256(value);
477 : }
478 0 : break;
479 :
480 0 : case struct_type_t::STRUCT_TYPE_INT256:
481 : {
482 0 : int512_t value;
483 0 : value.f_value[0] = get_uint64();
484 0 : value.f_value[1] = get_uint64();
485 0 : value.f_value[2] = get_uint64();
486 0 : value.f_value[3] = get_uint64();
487 0 : value.f_value[4] = static_cast<int64_t>(value.f_value[3]) < 0 ? -1 : 0;
488 0 : value.f_value[5] = value.f_value[4];
489 0 : value.f_value[6] = value.f_value[4];
490 0 : value.f_high_value = value.f_value[4];
491 0 : v->set_int256(value);
492 : }
493 0 : break;
494 :
495 0 : case struct_type_t::STRUCT_TYPE_BITS512:
496 : case struct_type_t::STRUCT_TYPE_UINT512:
497 : {
498 0 : uint512_t value;
499 0 : value.f_value[0] = get_uint64();
500 0 : value.f_value[1] = get_uint64();
501 0 : value.f_value[2] = get_uint64();
502 0 : value.f_value[3] = get_uint64();
503 0 : value.f_value[4] = get_uint64();
504 0 : value.f_value[5] = get_uint64();
505 0 : value.f_value[6] = get_uint64();
506 0 : value.f_value[7] = get_uint64();
507 0 : v->set_uint512(value);
508 : }
509 0 : break;
510 :
511 0 : case struct_type_t::STRUCT_TYPE_INT512:
512 : {
513 0 : int512_t value;
514 0 : value.f_value[0] = get_uint64();
515 0 : value.f_value[1] = get_uint64();
516 0 : value.f_value[2] = get_uint64();
517 0 : value.f_value[3] = get_uint64();
518 0 : value.f_value[4] = get_uint64();
519 0 : value.f_value[5] = get_uint64();
520 0 : value.f_value[6] = get_uint64();
521 0 : value.f_value[7] = get_uint64();
522 0 : v->set_int512(value);
523 : }
524 0 : break;
525 :
526 0 : case struct_type_t::STRUCT_TYPE_FLOAT32:
527 : {
528 0 : uint32_t const value(get_uint32());
529 0 : v->set_float32(*reinterpret_cast<float const *>(&value));
530 : }
531 0 : break;
532 :
533 0 : case struct_type_t::STRUCT_TYPE_FLOAT64:
534 : {
535 0 : uint64_t const value(get_uint64());
536 0 : v->set_float64(*reinterpret_cast<double const *>(&value));
537 : }
538 0 : break;
539 :
540 0 : case struct_type_t::STRUCT_TYPE_FLOAT128:
541 : {
542 0 : uint64_t const value[2] = { get_uint64(), get_uint64() };
543 0 : v->set_float128(*reinterpret_cast<long double const *>(value));
544 : }
545 0 : break;
546 :
547 0 : case struct_type_t::STRUCT_TYPE_P8STRING:
548 : {
549 0 : if(pos >= blob.size())
550 : {
551 0 : throw unexpected_eof("blob too small for this string.");
552 : }
553 :
554 0 : uint8_t const size(get_uint8());
555 :
556 0 : if(pos + size > blob.size())
557 : {
558 0 : throw unexpected_eof("blob too small for this string.");
559 : }
560 :
561 0 : v->set_string(std::string(blob.data() + pos, blob.data() + pos + size));
562 0 : pos += size;
563 : }
564 0 : break;
565 :
566 0 : case struct_type_t::STRUCT_TYPE_P16STRING:
567 : {
568 0 : if(pos >= blob.size())
569 : {
570 0 : throw unexpected_eof("blob too small for this string.");
571 : }
572 :
573 0 : uint16_t const size(get_uint16());
574 :
575 0 : if(pos + size > blob.size())
576 : {
577 0 : throw unexpected_eof("blob too small for this string.");
578 : }
579 :
580 0 : v->set_string(std::string(blob.data() + pos, blob.data() + pos + size));
581 0 : pos += size;
582 : }
583 0 : break;
584 :
585 0 : case struct_type_t::STRUCT_TYPE_P32STRING:
586 : {
587 0 : if(pos >= blob.size())
588 : {
589 0 : throw unexpected_eof("blob too small for this string.");
590 : }
591 :
592 0 : uint32_t const size(get_uint32());
593 :
594 0 : if(pos + size > blob.size())
595 : {
596 0 : throw unexpected_eof("blob too small for this string.");
597 : }
598 :
599 0 : v->set_string(std::string(blob.data() + pos, blob.data() + pos + size));
600 0 : pos += size;
601 : }
602 0 : break;
603 :
604 0 : case struct_type_t::STRUCT_TYPE_STRUCTURE:
605 : case struct_type_t::STRUCT_TYPE_ARRAY8:
606 : case struct_type_t::STRUCT_TYPE_ARRAY16:
607 : case struct_type_t::STRUCT_TYPE_ARRAY32:
608 : case struct_type_t::STRUCT_TYPE_BUFFER8:
609 : case struct_type_t::STRUCT_TYPE_BUFFER16:
610 : case struct_type_t::STRUCT_TYPE_BUFFER32:
611 : case struct_type_t::STRUCT_TYPE_END:
612 : case struct_type_t::STRUCT_TYPE_RENAMED:
613 : throw type_mismatch(
614 : "Unexpected type ("
615 0 : + std::to_string(static_cast<int>(it->second->type()))
616 0 : + ") to convert a cell from binary.");
617 :
618 : }
619 :
620 0 : f_cells[it->second->name()] = v;
621 : }
622 0 : }
623 :
624 :
625 0 : cell::map_t row::cells() const
626 : {
627 0 : return f_cells;
628 : }
629 :
630 :
631 :
632 : } // namespace snapdatabase
633 : // vim: ts=4 sw=4 et
|