1 | /* |
2 | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
5 | * |
6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | #include "monetdb_config.h" |
10 | #include "bat_storage.h" |
11 | #include "bat_utils.h" |
12 | #include "sql_string.h" |
13 | #include "algebra.h" |
14 | #include "gdk_atoms.h" |
15 | |
16 | #define SNAPSHOT_MINSIZE ((BUN) 1024*128) |
17 | |
18 | static MT_Lock destroy_lock = MT_LOCK_INITIALIZER("destroy_lock" ); |
19 | sql_dbat *tobe_destroyed_dbat = NULL; |
20 | sql_delta *tobe_destroyed_delta = NULL; |
21 | |
22 | static sql_trans * |
23 | oldest_active_transaction(void) |
24 | { |
25 | sql_session *s = active_sessions->h->data; |
26 | return s->tr; |
27 | } |
28 | |
29 | sql_delta * |
30 | timestamp_delta( sql_delta *d, int ts) |
31 | { |
32 | while (d->next && d->wtime > ts) |
33 | d = d->next; |
34 | return d; |
35 | } |
36 | |
37 | sql_dbat * |
38 | timestamp_dbat( sql_dbat *d, int ts) |
39 | { |
40 | while (d->next && d->wtime > ts) |
41 | d = d->next; |
42 | return d; |
43 | } |
44 | |
45 | static BAT * |
46 | delta_bind_del(sql_dbat *bat, int access) |
47 | { |
48 | BAT *b; |
49 | |
50 | (void) access; |
51 | assert(access == RDONLY || access == RD_INS); |
52 | assert(access != RD_UPD_ID && access != RD_UPD_VAL); |
53 | |
54 | b = temp_descriptor(bat->dbid); |
55 | assert(BATcount(b) == bat->cnt); |
56 | return b; |
57 | } |
58 | |
59 | static BAT * |
60 | bind_del(sql_trans *tr, sql_table *t, int access) |
61 | { |
62 | assert(tr == gtrans || access == QUICK || tr->active); |
63 | if (!t->data) { |
64 | sql_table *ot = tr_find_table(tr->parent, t); |
65 | t->data = timestamp_dbat(ot->data, t->base.stime); |
66 | } |
67 | assert(!store_initialized || tr != gtrans); |
68 | t->s->base.rtime = t->base.rtime = tr->stime; |
69 | return delta_bind_del(t->data, access); |
70 | } |
71 | |
72 | static BAT * |
73 | delta_bind_ubat(sql_delta *bat, int access, int type) |
74 | { |
75 | BAT *b; |
76 | log_bid bb; |
77 | |
78 | (void) access; |
79 | assert(access == RD_UPD_ID || access == RD_UPD_VAL); |
80 | if (bat->uibid && bat->uvbid) { |
81 | if (access == RD_UPD_ID) |
82 | b = temp_descriptor(bat->uibid); |
83 | else |
84 | b = temp_descriptor(bat->uvbid); |
85 | } else { |
86 | if (access == RD_UPD_ID) { |
87 | bb = e_bat(TYPE_oid); |
88 | if(bb == BID_NIL) |
89 | return NULL; |
90 | b = temp_descriptor(bb); |
91 | } else { |
92 | bb = e_bat(type); |
93 | if(bb == BID_NIL) |
94 | return NULL; |
95 | b = temp_descriptor(bb); |
96 | } |
97 | } |
98 | return b; |
99 | } |
100 | |
101 | static BAT * |
102 | bind_ucol(sql_trans *tr, sql_column *c, int access) |
103 | { |
104 | BAT *u = NULL; |
105 | |
106 | assert(tr == gtrans || tr->active); |
107 | if (!c->data) { |
108 | sql_column *oc = tr_find_column(tr->parent, c); |
109 | c->data = timestamp_delta(oc->data, c->base.stime); |
110 | } |
111 | if (!c->t->data) { |
112 | sql_table *ot = tr_find_table(tr->parent, c->t); |
113 | c->t->data = timestamp_dbat(ot->data, c->t->base.stime); |
114 | } |
115 | assert(tr != gtrans); |
116 | c->t->s->base.rtime = c->t->base.rtime = c->base.rtime = tr->stime; |
117 | u = delta_bind_ubat(c->data, access, c->type.type->localtype); |
118 | return u; |
119 | } |
120 | |
121 | static BAT * |
122 | bind_uidx(sql_trans *tr, sql_idx * i, int access) |
123 | { |
124 | BAT *u = NULL; |
125 | |
126 | assert(tr == gtrans || tr->active); |
127 | if (!i->data) { |
128 | sql_idx *oi = tr_find_idx(tr->parent, i); |
129 | i->data = timestamp_delta(oi->data, i->base.stime); |
130 | } |
131 | if (!i->t->data) { |
132 | sql_table *ot = tr_find_table(tr->parent, i->t); |
133 | i->t->data = timestamp_dbat(ot->data, i->t->base.stime); |
134 | } |
135 | assert(tr != gtrans); |
136 | i->base.rtime = i->t->base.rtime = i->t->s->base.rtime = tr->rtime = tr->stime; |
137 | u = delta_bind_ubat(i->data, access, (oid_index(i->type))?TYPE_oid:TYPE_lng); |
138 | return u; |
139 | } |
140 | |
141 | static BAT * |
142 | delta_bind_bat( sql_delta *bat, int access, int temp) |
143 | { |
144 | BAT *b; |
145 | |
146 | assert(access == RDONLY || access == RD_INS || access == QUICK); |
147 | assert(bat != NULL); |
148 | if (access == QUICK) |
149 | return quick_descriptor(bat->bid); |
150 | if (temp || access == RD_INS) { |
151 | assert(bat->ibid); |
152 | b = temp_descriptor(bat->ibid); |
153 | if (b == NULL) |
154 | return NULL; |
155 | if (BATcount(b) && bat->uibid && bat->uvbid) { |
156 | /* apply updates to the inserted */ |
157 | BAT *ui = temp_descriptor(bat->uibid), *uv = temp_descriptor(bat->uvbid), *nui = ui, *nuv = uv, *o; |
158 | |
159 | if (ui == NULL || uv == NULL) { |
160 | bat_destroy(ui); |
161 | bat_destroy(uv); |
162 | bat_destroy(b); |
163 | return NULL; |
164 | } |
165 | if (!isEbat(nui) && BATcount(nui)) { |
166 | o = BATselect(ui, NULL, &b->hseqbase, ATOMnilptr(ui->ttype), true, false, false); |
167 | if (o == NULL) { |
168 | bat_destroy(ui); |
169 | bat_destroy(uv); |
170 | bat_destroy(b); |
171 | return NULL; |
172 | } |
173 | nui = BATproject(o, ui); |
174 | bat_destroy(ui); |
175 | nuv = BATproject(o, uv); |
176 | bat_destroy(uv); |
177 | bat_destroy(o); |
178 | if (nui == NULL || |
179 | nuv == NULL || |
180 | void_replace_bat(b, nui, nuv, true) != GDK_SUCCEED) { |
181 | bat_destroy(nui); |
182 | bat_destroy(nuv); |
183 | bat_destroy(b); |
184 | return NULL; |
185 | } |
186 | } |
187 | bat_destroy(nui); |
188 | bat_destroy(nuv); |
189 | } |
190 | } else if (!bat->bid) { |
191 | int tt = 0; |
192 | b = temp_descriptor(bat->ibid); |
193 | if (b == NULL) |
194 | return NULL; |
195 | tt = b->ttype; |
196 | bat_destroy(b); |
197 | b = e_BAT(tt); |
198 | if (b == NULL) |
199 | return NULL; |
200 | } else { |
201 | b = temp_descriptor(bat->bid); |
202 | if (b == NULL) |
203 | return NULL; |
204 | bat_set_access(b, BAT_READ); |
205 | } |
206 | assert(b); |
207 | return b; |
208 | } |
209 | |
210 | static BAT * |
211 | bind_col(sql_trans *tr, sql_column *c, int access) |
212 | { |
213 | assert(tr == gtrans || access == QUICK || tr->active); |
214 | if (!isTable(c->t)) |
215 | return NULL; |
216 | if (!c->data) { |
217 | sql_column *oc = tr_find_column(tr->parent, c); |
218 | c->data = timestamp_delta(oc->data, c->base.stime); |
219 | } |
220 | if (access == RD_UPD_ID || access == RD_UPD_VAL) |
221 | return bind_ucol(tr, c, access); |
222 | assert(access == QUICK || tr != gtrans); |
223 | if (tr && access != QUICK) |
224 | c->base.rtime = c->t->base.rtime = c->t->s->base.rtime = tr->rtime = tr->stime; |
225 | return delta_bind_bat( c->data, access, isTemp(c)); |
226 | } |
227 | |
228 | static BAT * |
229 | bind_idx(sql_trans *tr, sql_idx * i, int access) |
230 | { |
231 | assert(tr == gtrans || access == QUICK || tr->active); |
232 | if (!isTable(i->t)) |
233 | return NULL; |
234 | if (!i->data) { |
235 | sql_idx *oi = tr_find_idx(tr->parent, i); |
236 | i->data = timestamp_delta(oi->data, i->base.stime); |
237 | } |
238 | if (access == RD_UPD_ID || access == RD_UPD_VAL) |
239 | return bind_uidx(tr, i, access); |
240 | assert(access == QUICK || tr != gtrans); |
241 | if (tr && access != QUICK) |
242 | i->base.rtime = i->t->base.rtime = i->t->s->base.rtime = tr->rtime = tr->stime; |
243 | return delta_bind_bat( i->data, access, isTemp(i)); |
244 | } |
245 | |
246 | static int |
247 | delta_update_bat( sql_delta *bat, BAT *tids, BAT *updates, int is_new) |
248 | { |
249 | BAT *b, *ui = NULL, *uv = NULL; |
250 | gdk_return ret; |
251 | |
252 | if (!BATcount(tids)) |
253 | return LOG_OK; |
254 | |
255 | if (bat->cached) { |
256 | bat_destroy(bat->cached); |
257 | bat->cached = NULL; |
258 | } |
259 | if (!is_new && bat->uibid && bat->uvbid) { |
260 | BAT *ib = temp_descriptor(bat->ibid); |
261 | BAT *o = NULL; |
262 | |
263 | if (ib == NULL) |
264 | return LOG_ERR; |
265 | |
266 | if (BATcount(ib)) { |
267 | BAT *nui = tids, *nuv = updates; |
268 | |
269 | o = BATselect(tids, NULL, &ib->hseqbase, ATOMnilptr(tids->ttype), true, false, false); |
270 | if (o == NULL) { |
271 | bat_destroy(ib); |
272 | return LOG_ERR; |
273 | } |
274 | nui = BATproject(o, tids); |
275 | nuv = BATproject(o, updates); |
276 | bat_destroy(o); |
277 | if (nui == NULL || nuv == NULL) { |
278 | bat_destroy(ib); |
279 | bat_destroy(nui); |
280 | bat_destroy(nuv); |
281 | return LOG_ERR; |
282 | } |
283 | assert(BATcount(nui) == BATcount(nuv)); |
284 | ret = void_replace_bat(ib, nui, nuv, true); |
285 | bat_destroy(nui); |
286 | bat_destroy(nuv); |
287 | if (ret != GDK_SUCCEED) { |
288 | bat_destroy(ib); |
289 | return LOG_ERR; |
290 | } |
291 | |
292 | o = BATselect(tids, NULL, ATOMnilptr(tids->ttype), &ib->hseqbase, false, false, false); |
293 | if (o == NULL) { |
294 | bat_destroy(ib); |
295 | return LOG_ERR; |
296 | } |
297 | } |
298 | bat_destroy(ib); |
299 | |
300 | ui = temp_descriptor(bat->uibid); |
301 | uv = temp_descriptor(bat->uvbid); |
302 | if (ui == NULL || uv == NULL) { |
303 | bat_destroy(ui); |
304 | bat_destroy(uv); |
305 | return LOG_ERR; |
306 | } |
307 | assert(ui && uv); |
308 | if (isEbat(ui)){ |
309 | temp_destroy(bat->uibid); |
310 | bat->uibid = temp_copy(ui->batCacheid, false); |
311 | bat_destroy(ui); |
312 | if (bat->uibid == BID_NIL || |
313 | (ui = temp_descriptor(bat->uibid)) == NULL) { |
314 | bat_destroy(uv); |
315 | return LOG_ERR; |
316 | } |
317 | } |
318 | if (isEbat(uv)){ |
319 | temp_destroy(bat->uvbid); |
320 | bat->uvbid = temp_copy(uv->batCacheid, false); |
321 | bat_destroy(uv); |
322 | if (bat->uvbid == BID_NIL || |
323 | (uv = temp_descriptor(bat->uvbid)) == NULL) { |
324 | bat_destroy(ui); |
325 | return LOG_ERR; |
326 | } |
327 | } |
328 | if (BATappend(ui, tids, o, true) != GDK_SUCCEED || |
329 | BATappend(uv, updates, o, true) != GDK_SUCCEED) { |
330 | bat_destroy(ui); |
331 | bat_destroy(uv); |
332 | return LOG_ERR; |
333 | } |
334 | assert(BATcount(tids) == BATcount(updates)); |
335 | bat_destroy(o); |
336 | bat_destroy(ui); |
337 | bat_destroy(uv); |
338 | } else if (is_new && bat->bid) { |
339 | BAT *ib = temp_descriptor(bat->ibid); |
340 | b = temp_descriptor(bat->bid); |
341 | |
342 | if (b == NULL || ib == NULL) { |
343 | bat_destroy(b); |
344 | bat_destroy(ib); |
345 | return LOG_ERR; |
346 | } |
347 | if (BATcount(ib)) { |
348 | BAT *nui = tids, *nuv = updates, *o; |
349 | |
350 | o = BATselect(tids, NULL, &ib->hseqbase, ATOMnilptr(tids->ttype), true, false, false); |
351 | if (o == NULL) { |
352 | bat_destroy(b); |
353 | bat_destroy(ib); |
354 | return LOG_ERR; |
355 | } |
356 | nui = BATproject(o, tids); |
357 | nuv = BATproject(o, updates); |
358 | bat_destroy(o); |
359 | if (nui == NULL || nuv == NULL) { |
360 | bat_destroy(nui); |
361 | bat_destroy(nuv); |
362 | bat_destroy(b); |
363 | bat_destroy(ib); |
364 | return LOG_ERR; |
365 | } |
366 | assert(BATcount(nui) == BATcount(nuv)); |
367 | ret = void_replace_bat(ib, nui, nuv, true); |
368 | bat_destroy(nui); |
369 | bat_destroy(nuv); |
370 | if (ret != GDK_SUCCEED) { |
371 | bat_destroy(b); |
372 | bat_destroy(ib); |
373 | return LOG_ERR; |
374 | } |
375 | |
376 | o = BATselect(tids, NULL, ATOMnilptr(tids->ttype), &ib->hseqbase, false, false, false); |
377 | if (o == NULL) { |
378 | bat_destroy(b); |
379 | bat_destroy(ib); |
380 | return LOG_ERR; |
381 | } |
382 | nui = BATproject(o, tids); |
383 | nuv = BATproject(o, updates); |
384 | bat_destroy(o); |
385 | if (nui == NULL || nuv == NULL) { |
386 | bat_destroy(nui); |
387 | bat_destroy(nuv); |
388 | bat_destroy(b); |
389 | bat_destroy(ib); |
390 | return LOG_ERR; |
391 | } |
392 | assert(BATcount(nui) == BATcount(nuv)); |
393 | ret = void_replace_bat(b, nui, nuv, true); |
394 | bat_destroy(nui); |
395 | bat_destroy(nuv); |
396 | if (ret != GDK_SUCCEED) { |
397 | bat_destroy(b); |
398 | bat_destroy(ib); |
399 | return LOG_ERR; |
400 | } |
401 | } else { |
402 | if (void_replace_bat(b, tids, updates, true) != GDK_SUCCEED) { |
403 | bat_destroy(b); |
404 | bat_destroy(ib); |
405 | return LOG_ERR; |
406 | } |
407 | } |
408 | bat_destroy(ib); |
409 | bat_destroy(b); |
410 | } else { |
411 | b = temp_descriptor(bat->ibid); |
412 | if (b == NULL) |
413 | return LOG_ERR; |
414 | ret = void_replace_bat(b, tids, updates, true); |
415 | bat_destroy(b); |
416 | if (ret != GDK_SUCCEED) { |
417 | return LOG_ERR; |
418 | } |
419 | } |
420 | bat->ucnt += BATcount(tids); |
421 | return LOG_OK; |
422 | } |
423 | |
424 | static int |
425 | delta_update_val( sql_delta *bat, oid rid, void *upd) |
426 | { |
427 | BAT *b = NULL; |
428 | |
429 | assert(!is_oid_nil(rid)); |
430 | |
431 | if (bat->cached) { |
432 | bat_destroy(bat->cached); |
433 | bat->cached = NULL; |
434 | } |
435 | if (bat->uibid && bat->uvbid) { |
436 | BAT *ib = temp_descriptor(bat->ibid); |
437 | if(ib == NULL) |
438 | return LOG_ERR; |
439 | |
440 | if (BATcount(ib) && ib->hseqbase <= rid) { |
441 | /* ToDo what if rid updates 'old inserts' */ |
442 | if (void_inplace(ib, rid, upd, true) != GDK_SUCCEED) { |
443 | bat_destroy(ib); |
444 | return LOG_ERR; |
445 | } |
446 | } else { |
447 | BAT *ui = temp_descriptor(bat->uibid); |
448 | BAT *uv = temp_descriptor(bat->uvbid); |
449 | if(ui == NULL || uv == NULL) { |
450 | bat_destroy(ui); |
451 | bat_destroy(uv); |
452 | bat_destroy(ib); |
453 | return LOG_ERR; |
454 | } |
455 | |
456 | if (isEbat(ui)){ |
457 | temp_destroy(bat->uibid); |
458 | bat->uibid = temp_copy(ui->batCacheid, false); |
459 | if (bat->uibid == BID_NIL) |
460 | return LOG_ERR; |
461 | bat_destroy(ui); |
462 | ui = temp_descriptor(bat->uibid); |
463 | if(ui == NULL) { |
464 | bat_destroy(uv); |
465 | bat_destroy(ib); |
466 | return LOG_ERR; |
467 | } |
468 | } |
469 | if (isEbat(uv)){ |
470 | temp_destroy(bat->uvbid); |
471 | bat->uvbid = temp_copy(uv->batCacheid, false); |
472 | if (bat->uvbid == BID_NIL) |
473 | return LOG_ERR; |
474 | bat_destroy(uv); |
475 | uv = temp_descriptor(bat->uvbid); |
476 | if(uv == NULL) { |
477 | bat_destroy(ui); |
478 | bat_destroy(ib); |
479 | return LOG_ERR; |
480 | } |
481 | } |
482 | if (BUNappend(ui, (ptr) &rid, true) != GDK_SUCCEED || |
483 | BUNappend(uv, (ptr) upd, true) != GDK_SUCCEED) { |
484 | bat_destroy(ui); |
485 | bat_destroy(uv); |
486 | bat_destroy(ib); |
487 | return LOG_ERR; |
488 | } |
489 | bat->ucnt++; |
490 | bat_destroy(ui); |
491 | bat_destroy(uv); |
492 | } |
493 | bat_destroy(ib); |
494 | } else { |
495 | if((b = temp_descriptor(bat->ibid)) == NULL) |
496 | return LOG_ERR; |
497 | if (void_inplace(b, rid, upd, true) != GDK_SUCCEED) { |
498 | bat_destroy(b); |
499 | return LOG_ERR; |
500 | } |
501 | bat_destroy(b); |
502 | } |
503 | return LOG_OK; |
504 | } |
505 | |
506 | static int |
507 | dup_delta(sql_trans *tr, sql_delta *obat, sql_delta *bat, int type, int oc_isnew, int c_isnew, int temp, int sz) |
508 | { |
509 | if (!obat) |
510 | return LOG_OK; |
511 | bat->ibid = obat->ibid; |
512 | bat->bid = obat->bid; |
513 | bat->uibid = obat->uibid; |
514 | bat->uvbid = obat->uvbid; |
515 | bat->ibase = obat->ibase; |
516 | bat->cnt = obat->cnt; |
517 | bat->ucnt = obat->ucnt; |
518 | bat->wtime = obat->wtime; |
519 | bat->cleared = obat->cleared; |
520 | |
521 | bat->name = _STRDUP(obat->name); |
522 | if(!bat->name) |
523 | return LOG_ERR; |
524 | |
525 | if (!bat->ibid) |
526 | return LOG_OK; |
527 | if (bat->ibid) { |
528 | BAT *b; |
529 | if (temp) { |
530 | bat->ibid = temp_copy(bat->ibid, 1); |
531 | if (bat->ibid == BID_NIL) |
532 | return LOG_ERR; |
533 | } else if (oc_isnew && !bat->bid) { |
534 | /* move the bat to the new col, fixup the old col*/ |
535 | b = COLnew((oid) obat->cnt, type, sz, PERSISTENT); |
536 | if (b == NULL) |
537 | return LOG_ERR; |
538 | bat_set_access(b, BAT_READ); |
539 | obat->ibid = temp_create(b); |
540 | obat->ibase = bat->ibase = (oid) obat->cnt; |
541 | bat_destroy(b); |
542 | if (c_isnew && tr->parent == gtrans) { |
543 | /* new cols are moved to gtrans and bat.bid */ |
544 | temp_dup(bat->ibid); |
545 | obat->bid = bat->ibid; |
546 | } else if (!c_isnew) { |
547 | bat->bid = bat->ibid; |
548 | |
549 | b = COLnew(bat->ibase, type, sz, PERSISTENT); |
550 | if (b == NULL) |
551 | return LOG_ERR; |
552 | bat_set_access(b, BAT_READ); |
553 | bat->ibid = temp_create(b); |
554 | } |
555 | } else { /* old column */ |
556 | bat->ibid = ebat_copy(bat->ibid, bat->ibase, 0); |
557 | if (bat->ibid == BID_NIL) |
558 | return LOG_ERR; |
559 | } |
560 | } |
561 | if (!temp && bat->ibid) { |
562 | if (bat->uibid && bat->uvbid) { |
563 | if (c_isnew && tr->parent == gtrans) { |
564 | obat->uibid = ebat_copy(bat->uibid, 0, 0); |
565 | obat->uvbid = ebat_copy(bat->uvbid, 0, 0); |
566 | if (obat->uibid == BID_NIL || |
567 | obat->uvbid == BID_NIL) |
568 | return LOG_ERR; |
569 | } else { |
570 | bat->uibid = ebat_copy(bat->uibid, 0, 0); |
571 | bat->uvbid = ebat_copy(bat->uvbid, 0, 0); |
572 | if (bat->uibid == BID_NIL || |
573 | bat->uvbid == BID_NIL) |
574 | return LOG_ERR; |
575 | } |
576 | } else { |
577 | bat->uibid = e_bat(TYPE_oid); |
578 | obat->uvbid = e_bat(type); |
579 | if (bat->uibid == BID_NIL || obat->uvbid == BID_NIL) |
580 | return LOG_ERR; |
581 | } |
582 | } |
583 | if (bat->bid) |
584 | temp_dup(bat->bid); |
585 | return LOG_OK; |
586 | } |
587 | |
588 | int |
589 | dup_bat(sql_trans *tr, sql_table *t, sql_delta *obat, sql_delta *bat, int type, int oc_isnew, int c_isnew) |
590 | { |
591 | return dup_delta( tr, obat, bat, type, oc_isnew, c_isnew, isTempTable(t), t->sz); |
592 | } |
593 | |
594 | static int |
595 | update_col(sql_trans *tr, sql_column *c, void *tids, void *upd, int tpe) |
596 | { |
597 | BAT *b = tids; |
598 | sql_delta *bat; |
599 | |
600 | if (tpe == TYPE_bat && !BATcount(b)) |
601 | return LOG_OK; |
602 | |
603 | if (!c->data || !c->base.allocated) { |
604 | int type = c->type.type->localtype; |
605 | sql_column *oc = tr_find_column(tr->parent, c); |
606 | sql_delta* bat = ZNEW(sql_delta),*obat; |
607 | if(!bat) |
608 | return LOG_ERR; |
609 | c->data = bat; |
610 | obat = timestamp_delta(oc->data, c->base.stime); |
611 | if(dup_bat(tr, c->t, obat, bat, type, isNew(oc), isNew(c)) == LOG_ERR) |
612 | return LOG_ERR; |
613 | c->base.allocated = 1; |
614 | } |
615 | bat = c->data; |
616 | bat->wtime = c->base.wtime = c->t->base.wtime = c->t->s->base.wtime = tr->wtime = tr->wstime; |
617 | assert(tr != gtrans); |
618 | c->base.rtime = c->t->base.rtime = c->t->s->base.rtime = tr->rtime = tr->stime; |
619 | if (tpe == TYPE_bat) |
620 | return delta_update_bat(bat, tids, upd, isNew(c)); |
621 | else |
622 | return delta_update_val(bat, *(oid*)tids, upd); |
623 | } |
624 | |
625 | static int |
626 | update_idx(sql_trans *tr, sql_idx * i, void *tids, void *upd, int tpe) |
627 | { |
628 | BAT *b = tids; |
629 | sql_delta *bat; |
630 | |
631 | if (tpe == TYPE_bat && !BATcount(b)) |
632 | return LOG_OK; |
633 | |
634 | if (!i->data || !i->base.allocated) { |
635 | int type = (oid_index(i->type))?TYPE_oid:TYPE_lng; |
636 | sql_idx *oi = tr_find_idx(tr->parent, i); |
637 | sql_delta* bat = ZNEW(sql_delta), *obat; |
638 | if(!bat) |
639 | return LOG_ERR; |
640 | i->data = bat; |
641 | obat = timestamp_delta(oi->data, i->base.stime); |
642 | if(dup_bat(tr, i->t, obat, bat, type, isNew(i), isNew(i)) == LOG_ERR) |
643 | return LOG_ERR; |
644 | i->base.allocated = 1; |
645 | } |
646 | bat = i->data; |
647 | bat->wtime = i->base.wtime = i->t->base.wtime = i->t->s->base.wtime = tr->wtime = tr->wstime; |
648 | assert(tr != gtrans); |
649 | i->base.rtime = i->t->base.rtime = i->t->s->base.rtime = tr->rtime = tr->stime; |
650 | if (tpe == TYPE_bat) |
651 | return delta_update_bat(bat, tids, upd, isNew(i)); |
652 | else |
653 | assert(0); |
654 | return LOG_OK; |
655 | } |
656 | |
657 | static int |
658 | delta_append_bat( sql_delta *bat, BAT *i ) |
659 | { |
660 | int id = i->batCacheid; |
661 | BAT *b; |
662 | #ifndef NDEBUG |
663 | BAT *c = BBPquickdesc(bat->bid, false); |
664 | #endif |
665 | |
666 | if (!BATcount(i)) |
667 | return LOG_OK; |
668 | b = temp_descriptor(bat->ibid); |
669 | if (b == NULL) |
670 | return LOG_ERR; |
671 | |
672 | if (bat->cached) { |
673 | bat_destroy(bat->cached); |
674 | bat->cached = NULL; |
675 | } |
676 | assert(!c || BATcount(c) == bat->ibase); |
677 | if (BATcount(b) == 0 && BBP_refs(id) == 1 && BBP_lrefs(id) == 1 && !isVIEW(i) && i->ttype && i->batRole == PERSISTENT){ |
678 | temp_destroy(bat->ibid); |
679 | bat->ibid = id; |
680 | temp_dup(id); |
681 | BAThseqbase(i, bat->ibase); |
682 | } else { |
683 | if (!isEbat(b)){ |
684 | assert(b->theap.storage != STORE_PRIV); |
685 | } else { |
686 | temp_destroy(bat->ibid); |
687 | bat->ibid = ebat2real(b->batCacheid, bat->ibase); |
688 | bat_destroy(b); |
689 | if(bat->ibid != BID_NIL) { |
690 | b = temp_descriptor(bat->ibid); |
691 | if (b == NULL) |
692 | return LOG_ERR; |
693 | } else { |
694 | return LOG_ERR; |
695 | } |
696 | } |
697 | if (isVIEW(i) && b->batCacheid == VIEWtparent(i)) { |
698 | BAT *ic = COLcopy(i, i->ttype, true, TRANSIENT); |
699 | if (ic == NULL || BATappend(b, ic, NULL, true) != GDK_SUCCEED) { |
700 | if(ic) |
701 | bat_destroy(ic); |
702 | bat_destroy(b); |
703 | return LOG_ERR; |
704 | } |
705 | bat_destroy(ic); |
706 | } else if (BATappend(b, i, NULL, true) != GDK_SUCCEED) { |
707 | bat_destroy(b); |
708 | return LOG_ERR; |
709 | } |
710 | assert(BUNlast(b) > b->batInserted); |
711 | } |
712 | bat_destroy(b); |
713 | bat->cnt += BATcount(i); |
714 | return LOG_OK; |
715 | } |
716 | |
717 | static int |
718 | delta_append_val( sql_delta *bat, void *i ) |
719 | { |
720 | BAT *b = temp_descriptor(bat->ibid); |
721 | #ifndef NDEBUG |
722 | BAT *c = BBPquickdesc(bat->bid, false); |
723 | #endif |
724 | if(b == NULL) |
725 | return LOG_ERR; |
726 | |
727 | if (bat->cached) { |
728 | bat_destroy(bat->cached); |
729 | bat->cached = NULL; |
730 | } |
731 | assert(!c || BATcount(c) == bat->ibase); |
732 | if (isEbat(b)) { |
733 | bat_destroy(b); |
734 | temp_destroy(bat->ibid); |
735 | bat->ibid = ebat2real(bat->ibid, bat->ibase); |
736 | if(bat->ibid != BID_NIL) { |
737 | b = temp_descriptor(bat->ibid); |
738 | if (b == NULL) |
739 | return LOG_ERR; |
740 | } else { |
741 | return LOG_ERR; |
742 | } |
743 | } |
744 | if (BUNappend(b, i, true) != GDK_SUCCEED) { |
745 | bat_destroy(b); |
746 | return LOG_ERR; |
747 | } |
748 | assert(BUNlast(b) > b->batInserted); |
749 | bat->cnt ++; |
750 | bat_destroy(b); |
751 | return LOG_OK; |
752 | } |
753 | |
754 | static int |
755 | dup_col(sql_trans *tr, sql_column *oc, sql_column *c ) |
756 | { |
757 | int ok = LOG_OK; |
758 | |
759 | if (oc->data) { |
760 | int type = c->type.type->localtype; |
761 | sql_delta *bat = ZNEW(sql_delta), *obat = oc->data; |
762 | if (!bat) |
763 | ok = LOG_ERR; |
764 | else { |
765 | c->data = bat; |
766 | ok = dup_bat(tr, c->t, obat, bat, type, isNew(oc), isNew(c)); |
767 | c->base.allocated = 1; |
768 | } |
769 | } |
770 | return ok; |
771 | } |
772 | |
773 | static int |
774 | dup_idx(sql_trans *tr, sql_idx *i, sql_idx *ni ) |
775 | { |
776 | int ok = LOG_OK; |
777 | |
778 | if (!isTable(i->t) || !idx_has_column(i->type)) |
779 | return ok; |
780 | if (i->data) { |
781 | int type = (oid_index(ni->type))?TYPE_oid:TYPE_lng; |
782 | sql_delta *bat = ZNEW(sql_delta), *obat = i->data; |
783 | if (!bat) |
784 | ok = LOG_ERR; |
785 | else { |
786 | ni->data = bat; |
787 | ok = dup_bat(tr, ni->t, obat, bat, type, isNew(i), isNew(ni)); |
788 | ni->base.allocated = 1; |
789 | } |
790 | } |
791 | return ok; |
792 | } |
793 | |
794 | static int |
795 | dup_dbat( sql_trans *tr, sql_dbat *obat, sql_dbat *bat, int is_new, int temp) |
796 | { |
797 | bat->dbid = obat->dbid; |
798 | bat->cnt = obat->cnt; |
799 | bat->dname = _STRDUP(obat->dname); |
800 | bat->wtime = obat->wtime; |
801 | bat->cleared = obat->cleared; |
802 | if(!bat->dname) |
803 | return LOG_ERR; |
804 | if (bat->dbid) { |
805 | if (is_new) { |
806 | obat->dbid = temp_copy(bat->dbid, temp); |
807 | } else { |
808 | bat->dbid = ebat_copy(bat->dbid, 0, temp); |
809 | } |
810 | assert(BATcount(quick_descriptor(bat->dbid)) == bat->cnt); |
811 | if (bat->dbid == BID_NIL) |
812 | return LOG_ERR; |
813 | } |
814 | (void)tr; |
815 | return LOG_OK; |
816 | } |
817 | |
818 | static int |
819 | dup_del(sql_trans *tr, sql_table *ot, sql_table *t) |
820 | { |
821 | int ok; |
822 | sql_dbat *bat = ZNEW(sql_dbat), *obat = ot->data; |
823 | if (!bat) |
824 | return LOG_ERR; |
825 | t->data = bat; |
826 | ok = dup_dbat( tr, obat, bat, isNew(t), isTempTable(t)); |
827 | assert(t->base.allocated == 0); |
828 | t->base.allocated = 1; |
829 | return ok; |
830 | } |
831 | |
832 | static int |
833 | append_col(sql_trans *tr, sql_column *c, void *i, int tpe) |
834 | { |
835 | int ok = LOG_OK; |
836 | BAT *b = i; |
837 | sql_delta *bat; |
838 | |
839 | if (tpe == TYPE_bat && !BATcount(b)) |
840 | return ok; |
841 | |
842 | if (!c->data || !c->base.allocated) { |
843 | int type = c->type.type->localtype; |
844 | sql_column *oc = tr_find_column(tr->parent, c); |
845 | sql_delta *bat = ZNEW(sql_delta), *obat; |
846 | if (!bat) |
847 | ok = LOG_ERR; |
848 | else { |
849 | c->data = bat; |
850 | obat = timestamp_delta(oc->data, c->base.stime); |
851 | ok = dup_bat(tr, c->t, obat, bat, type, isNew(oc), isNew(c)); |
852 | if(ok == LOG_OK) |
853 | c->base.allocated = 1; |
854 | } |
855 | } |
856 | |
857 | if(ok == LOG_ERR) |
858 | return ok; |
859 | |
860 | bat = c->data; |
861 | /* appends only write */ |
862 | bat->wtime = c->base.wtime = c->t->base.wtime = c->t->s->base.wtime = tr->wtime = tr->wstime; |
863 | /* inserts are ordered with the current delta implementation */ |
864 | /* therefor mark appends as reads */ |
865 | assert(tr != gtrans); |
866 | c->t->s->base.rtime = c->t->base.rtime = tr->stime; |
867 | if (tpe == TYPE_bat) |
868 | ok = delta_append_bat(bat, i); |
869 | else |
870 | ok = delta_append_val(bat, i); |
871 | /* |
872 | if (!c->t->data || !c->t->base.allocated) { |
873 | sql_table *ot = tr_find_table(tr->parent, c->t); |
874 | sql_dbat *bat = ZNEW(sql_dbat), *obat; |
875 | if (!bat) |
876 | return LOG_ERR; |
877 | c->t->data = bat; |
878 | obat = timestamp_dbat(ot->data, c->t->base.stime); |
879 | dup_dbat(tr, obat, bat, isNew(ot), isTempTable(c->t)); |
880 | c->t->base.allocated = 1; |
881 | } |
882 | if (c->t && c->t->data && ((sql_dbat*)c->t->data)->cached) { |
883 | sql_dbat *bat = c->t->data; |
884 | |
885 | bat_destroy(bat->cached); |
886 | bat->cached = NULL; |
887 | } |
888 | */ |
889 | return ok; |
890 | } |
891 | |
892 | static int |
893 | append_idx(sql_trans *tr, sql_idx * i, void *ib, int tpe) |
894 | { |
895 | BAT *b = ib; |
896 | sql_delta *bat; |
897 | int ok = LOG_OK; |
898 | |
899 | if (tpe == TYPE_bat && !BATcount(b)) |
900 | return ok; |
901 | |
902 | if (!i->data || !i->base.allocated) { |
903 | int type = (oid_index(i->type))?TYPE_oid:TYPE_lng; |
904 | sql_idx *oi = tr_find_idx(tr->parent, i); |
905 | sql_delta *bat = ZNEW(sql_delta), *obat; |
906 | if(!bat) |
907 | ok = LOG_ERR; |
908 | else { |
909 | i->data = bat; |
910 | obat = timestamp_delta(oi->data, i->base.stime); |
911 | ok = dup_bat(tr, i->t, obat, bat, type, isNew(i), isNew(i)); |
912 | if(ok != LOG_ERR) |
913 | i->base.allocated = 1; |
914 | } |
915 | } |
916 | |
917 | if(ok == LOG_ERR) |
918 | return ok; |
919 | |
920 | bat = i->data; |
921 | /* appends only write */ |
922 | bat->wtime = i->base.wtime = i->t->base.wtime = i->t->s->base.wtime = tr->wtime = tr->wstime; |
923 | if (tpe == TYPE_bat) |
924 | ok = delta_append_bat(bat, ib); |
925 | else |
926 | ok = delta_append_val(bat, ib); |
927 | /* |
928 | if (!i->t->data || !i->t->base.allocated) { |
929 | sql_table *ot = tr_find_table(tr->parent, i->t); |
930 | sql_dbat *bat = ZNEW(sql_dbat), *obat; |
931 | if(!bat) |
932 | return LOG_ERR; |
933 | i->t->data = bat; |
934 | obat = timestamp_dbat(ot->data, i->t->base.stime); |
935 | dup_dbat(tr, obat, bat, isNew(ot), isTempTable(i->t)); |
936 | i->t->base.allocated = 1; |
937 | } |
938 | |
939 | if (i->t && i->t->data && ((sql_dbat*)i->t->data)->cached) { |
940 | sql_dbat *bat = i->t->data; |
941 | |
942 | bat_destroy(bat->cached); |
943 | bat->cached = NULL; |
944 | } |
945 | */ |
946 | return ok; |
947 | } |
948 | |
949 | static int |
950 | delta_delete_bat( sql_dbat *bat, BAT *i ) |
951 | { |
952 | BAT *b = temp_descriptor(bat->dbid); |
953 | |
954 | if(!b) |
955 | return LOG_ERR; |
956 | |
957 | if (isEbat(b)) { |
958 | temp_destroy(bat->dbid); |
959 | bat->dbid = temp_copy(b->batCacheid, FALSE); |
960 | if (bat->dbid == BID_NIL) |
961 | return LOG_ERR; |
962 | bat_destroy(b); |
963 | b = temp_descriptor(bat->dbid); |
964 | if (b == NULL) |
965 | return LOG_ERR; |
966 | } |
967 | assert(b->theap.storage != STORE_PRIV); |
968 | assert(BATcount(b) == bat->cnt); |
969 | if (BATappend(b, i, NULL, true) != GDK_SUCCEED) { |
970 | bat_destroy(b); |
971 | return LOG_ERR; |
972 | } |
973 | BATkey(b, true); |
974 | assert(BATcount(b) == bat->cnt+ BATcount(i)); |
975 | bat_destroy(b); |
976 | |
977 | bat->cnt += BATcount(i); |
978 | return LOG_OK; |
979 | } |
980 | |
981 | static int |
982 | delta_delete_val( sql_dbat *bat, oid rid ) |
983 | { |
984 | BAT *b = temp_descriptor(bat->dbid); |
985 | |
986 | if (isEbat(b)) { |
987 | temp_destroy(bat->dbid); |
988 | bat->dbid = temp_copy(b->batCacheid, FALSE); |
989 | if (bat->dbid == BID_NIL) |
990 | return LOG_ERR; |
991 | bat_destroy(b); |
992 | b = temp_descriptor(bat->dbid); |
993 | if (b == NULL) |
994 | return LOG_ERR; |
995 | } |
996 | assert(b->theap.storage != STORE_PRIV); |
997 | assert(BATcount(b) == bat->cnt); |
998 | if (BUNappend(b, (ptr)&rid, true) != GDK_SUCCEED) { |
999 | bat_destroy(b); |
1000 | return LOG_ERR; |
1001 | } |
1002 | BATkey(b, true); |
1003 | bat_destroy(b); |
1004 | |
1005 | bat->cnt ++; |
1006 | return LOG_OK; |
1007 | } |
1008 | |
1009 | static int |
1010 | delete_tab(sql_trans *tr, sql_table * t, void *ib, int tpe) |
1011 | { |
1012 | BAT *b = ib; |
1013 | sql_dbat *bat; |
1014 | node *n; |
1015 | int ok = LOG_OK; |
1016 | |
1017 | if (tpe == TYPE_bat && !BATcount(b)) |
1018 | return ok; |
1019 | |
1020 | if (!t->data || !t->base.allocated) { |
1021 | sql_table *ot = tr_find_table(tr->parent, t); |
1022 | sql_dbat *bat = ZNEW(sql_dbat), *obat; |
1023 | if(!bat) |
1024 | return LOG_ERR; |
1025 | t->data = bat; |
1026 | obat = timestamp_dbat(ot->data, t->base.stime); |
1027 | dup_dbat(tr, obat, bat, isNew(ot), isTempTable(t)); |
1028 | t->base.allocated = 1; |
1029 | } |
1030 | bat = t->data; |
1031 | /* delete all cached copies */ |
1032 | |
1033 | if (bat->cached) { |
1034 | bat_destroy(bat->cached); |
1035 | bat->cached = NULL; |
1036 | } |
1037 | for (n = t->columns.set->h; n; n = n->next) { |
1038 | sql_column *c = n->data; |
1039 | sql_delta *bat; |
1040 | |
1041 | if (!c->data) { |
1042 | sql_column *oc = tr_find_column(tr->parent, c); |
1043 | c->data = timestamp_delta(oc->data, c->base.stime); |
1044 | } |
1045 | bat = c->data; |
1046 | if (bat->cached) { |
1047 | bat_destroy(bat->cached); |
1048 | bat->cached = NULL; |
1049 | } |
1050 | } |
1051 | if (t->idxs.set) { |
1052 | for (n = t->idxs.set->h; n; n = n->next) { |
1053 | sql_idx *i = n->data; |
1054 | sql_delta *bat; |
1055 | |
1056 | if (!isTable(i->t) || !idx_has_column(i->type)) |
1057 | continue; |
1058 | if (!i->data) { |
1059 | sql_idx *oi = tr_find_idx(tr->parent, i); |
1060 | i->data = timestamp_delta(oi->data, i->base.stime); |
1061 | } |
1062 | bat = i->data; |
1063 | if (bat && bat->cached) { |
1064 | bat_destroy(bat->cached); |
1065 | bat->cached = NULL; |
1066 | } |
1067 | } |
1068 | } |
1069 | |
1070 | /* deletes only write */ |
1071 | bat->wtime = t->base.wtime = t->s->base.wtime = tr->wtime = tr->wstime; |
1072 | if (tpe == TYPE_bat) |
1073 | ok = delta_delete_bat(bat, ib); |
1074 | else |
1075 | ok = delta_delete_val(bat, *(oid*)ib); |
1076 | return ok; |
1077 | } |
1078 | |
1079 | static size_t |
1080 | count_col(sql_trans *tr, sql_column *c, int all) |
1081 | { |
1082 | sql_delta *b; |
1083 | |
1084 | if (!isTable(c->t)) |
1085 | return 0; |
1086 | if (!c->data) { |
1087 | sql_column *oc = tr_find_column(tr->parent, c); |
1088 | c->data = timestamp_delta(oc->data, c->base.stime); |
1089 | } |
1090 | b = c->data; |
1091 | if (!b) |
1092 | return 1; |
1093 | if (all) |
1094 | return b->cnt; |
1095 | else |
1096 | return b->cnt - b->ibase; |
1097 | } |
1098 | |
1099 | static size_t |
1100 | dcount_col(sql_trans *tr, sql_column *c) |
1101 | { |
1102 | sql_delta *b; |
1103 | |
1104 | if (!isTable(c->t)) |
1105 | return 0; |
1106 | if (!c->data) { |
1107 | sql_column *oc = tr_find_column(tr->parent, c); |
1108 | c->data = timestamp_delta(oc->data, c->base.stime); |
1109 | } |
1110 | b = c->data; |
1111 | if (!b) |
1112 | return 1; |
1113 | if (b->cnt > 1024) { |
1114 | size_t dcnt = 0; |
1115 | dbl f = 1.0; |
1116 | BAT *v = delta_bind_bat(b, RDONLY, 0), *o = v, *u; |
1117 | |
1118 | if ((dcnt = (size_t) BATcount(v)) > 1024*1024) { |
1119 | v = BATsample(v, 1024); |
1120 | f = dcnt/1024.0; |
1121 | } |
1122 | u = BATunique(v, NULL); |
1123 | bat_destroy(o); |
1124 | if (v!=o) |
1125 | bat_destroy(v); |
1126 | dcnt = (size_t) (BATcount(u) * f); |
1127 | bat_destroy(u); |
1128 | return dcnt; |
1129 | } else { |
1130 | return 64; |
1131 | } |
1132 | } |
1133 | |
1134 | static size_t |
1135 | count_idx(sql_trans *tr, sql_idx *i, int all) |
1136 | { |
1137 | sql_delta *b; |
1138 | |
1139 | if (!isTable(i->t) || !idx_has_column(i->type)) |
1140 | return 0; |
1141 | if (!i->data) { |
1142 | sql_idx *oi = tr_find_idx(tr->parent, i); |
1143 | i->data = timestamp_delta(oi->data, i->base.stime); |
1144 | } |
1145 | b = i->data; |
1146 | if (!b) |
1147 | return 0; |
1148 | if (all) |
1149 | return b->cnt; |
1150 | else |
1151 | return b->cnt - b->ibase; |
1152 | } |
1153 | |
1154 | static size_t |
1155 | count_del(sql_trans *tr, sql_table *t) |
1156 | { |
1157 | sql_dbat *d; |
1158 | |
1159 | if (!isTable(t)) |
1160 | return 0; |
1161 | if (!t->data) { |
1162 | sql_table *ot = tr_find_table(tr->parent, t); |
1163 | t->data = timestamp_dbat(ot->data, t->base.stime); |
1164 | } |
1165 | d = t->data; |
1166 | if (!d) |
1167 | return 0; |
1168 | return d->cnt; |
1169 | } |
1170 | |
1171 | static size_t |
1172 | count_col_upd(sql_trans *tr, sql_column *c) |
1173 | { |
1174 | sql_delta *b; |
1175 | |
1176 | assert (isTable(c->t)) ; |
1177 | if (!c->data) { |
1178 | sql_column *oc = tr_find_column(tr->parent, c); |
1179 | c->data = timestamp_delta(oc->data, c->base.stime); |
1180 | } |
1181 | b = c->data; |
1182 | if (!b) |
1183 | return 1; |
1184 | return b->ucnt; |
1185 | } |
1186 | |
1187 | static size_t |
1188 | count_idx_upd(sql_trans *tr, sql_idx *i) |
1189 | { |
1190 | sql_delta *b; |
1191 | |
1192 | if (!isTable(i->t) || !idx_has_column(i->type)) |
1193 | return 0; |
1194 | if (!i->data) { |
1195 | sql_idx *oi = tr_find_idx(tr->parent, i); |
1196 | if (oi) |
1197 | i->data = timestamp_delta(oi->data, i->base.stime); |
1198 | } |
1199 | b = i->data; |
1200 | if (!b) |
1201 | return 0; |
1202 | return b->ucnt; |
1203 | } |
1204 | |
1205 | static size_t |
1206 | count_upd(sql_trans *tr, sql_table *t) |
1207 | { |
1208 | node *n; |
1209 | |
1210 | if (!isTable(t)) |
1211 | return 0; |
1212 | |
1213 | for( n = t->columns.set->h; n; n = n->next) { |
1214 | sql_column *c = n->data; |
1215 | |
1216 | if (count_col_upd(tr, c)) |
1217 | return 1; |
1218 | } |
1219 | if (t->idxs.set) |
1220 | for( n = t->idxs.set->h; n; n = n->next) { |
1221 | sql_idx *i = n->data; |
1222 | |
1223 | if (!isTable(i->t) || !idx_has_column(i->type)) |
1224 | continue; |
1225 | if (count_idx_upd(tr, i)) |
1226 | return 1; |
1227 | } |
1228 | return 0; |
1229 | } |
1230 | |
1231 | static int |
1232 | sorted_col(sql_trans *tr, sql_column *col) |
1233 | { |
1234 | int sorted = 0; |
1235 | |
1236 | if (!isTable(col->t) || !col->t->s) |
1237 | return 0; |
1238 | /* fallback to central bat */ |
1239 | if (tr && tr->parent && !col->data && col->po) |
1240 | col = col->po; |
1241 | |
1242 | if (col && col->data) { |
1243 | BAT *b = bind_col(tr, col, QUICK); |
1244 | |
1245 | if (b) |
1246 | sorted = BATtordered(b); |
1247 | } |
1248 | return sorted; |
1249 | } |
1250 | |
1251 | static int |
1252 | double_elim_col(sql_trans *tr, sql_column *col) |
1253 | { |
1254 | int de = 0; |
1255 | |
1256 | if (!isTable(col->t) || !col->t->s) |
1257 | return 0; |
1258 | /* fallback to central bat */ |
1259 | if (tr && tr->parent && !col->data && col->po) |
1260 | col = col->po; |
1261 | |
1262 | if (col && col->data) { |
1263 | BAT *b = bind_col(tr, col, QUICK); |
1264 | |
1265 | if (b && b->tvarsized) /* check double elimination */ |
1266 | de = GDK_ELIMDOUBLES(b->tvheap); |
1267 | if (de) |
1268 | de = b->twidth; |
1269 | } |
1270 | return de; |
1271 | } |
1272 | |
1273 | static int |
1274 | load_delta(sql_delta *bat, int bid, int type) |
1275 | { |
1276 | BAT *b; |
1277 | |
1278 | b = quick_descriptor(bid); |
1279 | if (!b) |
1280 | return LOG_ERR; |
1281 | bat->bid = temp_create(b); |
1282 | bat->ibase = BATcount(b); |
1283 | bat->cnt = bat->ibase; |
1284 | bat->ucnt = 0; |
1285 | bat->uibid = e_bat(TYPE_oid); |
1286 | bat->uvbid = e_bat(type); |
1287 | bat->ibid = e_bat(type); |
1288 | if(bat->uibid == BID_NIL || bat->uvbid == BID_NIL || bat->ibid == BID_NIL) { |
1289 | return LOG_ERR; |
1290 | } |
1291 | return LOG_OK; |
1292 | } |
1293 | |
1294 | static int |
1295 | load_bat(sql_delta *bat, int type, char tpe, oid id) |
1296 | { |
1297 | int bid = logger_find_bat(bat_logger, bat->name, tpe, id); |
1298 | |
1299 | return load_delta(bat, bid, type); |
1300 | } |
1301 | |
1302 | static int |
1303 | log_create_delta(sql_delta *bat, char tpe, oid id) |
1304 | { |
1305 | int res = LOG_OK; |
1306 | gdk_return ok; |
1307 | BAT *b = (bat->bid)? |
1308 | temp_descriptor(bat->bid): |
1309 | temp_descriptor(bat->ibid); |
1310 | |
1311 | if (b == NULL) |
1312 | return LOG_ERR; |
1313 | |
1314 | if (!bat->uibid) |
1315 | bat->uibid = e_bat(TYPE_oid); |
1316 | if (!bat->uvbid) |
1317 | bat->uvbid = e_bat(b->ttype); |
1318 | if (bat->uibid == BID_NIL || bat->uvbid == BID_NIL) |
1319 | res = LOG_ERR; |
1320 | if (GDKinmemory()) |
1321 | return res; |
1322 | |
1323 | ok = logger_add_bat(bat_logger, b, bat->name, tpe, id); |
1324 | if (ok == GDK_SUCCEED) |
1325 | ok = log_bat_persists(bat_logger, b, bat->name, tpe, id); |
1326 | bat_destroy(b); |
1327 | if(res != LOG_OK) |
1328 | return res; |
1329 | return ok == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
1330 | } |
1331 | |
1332 | static int |
1333 | snapshot_new_persistent_bat(sql_trans *tr, sql_delta *bat) |
1334 | { |
1335 | int ok = LOG_OK; |
1336 | BAT *b = (bat->bid)? |
1337 | temp_descriptor(bat->bid): |
1338 | temp_descriptor(bat->ibid); |
1339 | |
1340 | if (b == NULL) |
1341 | return LOG_ERR; |
1342 | |
1343 | (void)tr; |
1344 | /* snapshot large bats */ |
1345 | bat_set_access(b, BAT_READ); |
1346 | if (BATcount(b) > SNAPSHOT_MINSIZE) |
1347 | BATmode(b, false); |
1348 | bat_destroy(b); |
1349 | return ok; |
1350 | } |
1351 | |
1352 | static int |
1353 | new_persistent_delta( sql_delta *bat, int sz ) |
1354 | { |
1355 | if (bat->bid) { /* result of alter ! */ |
1356 | BAT *b = temp_descriptor(bat->bid); |
1357 | BAT *i = temp_descriptor(bat->ibid); |
1358 | |
1359 | if (b == NULL || i == NULL) { |
1360 | bat_destroy(b); |
1361 | bat_destroy(i); |
1362 | return LOG_ERR; |
1363 | } |
1364 | bat->ibase = BATcount(b); |
1365 | bat->cnt = BATcount(b) + BATcount(i); |
1366 | bat->ucnt = 0; |
1367 | bat->ibid = temp_copy(i->batCacheid, FALSE); |
1368 | bat_destroy(i); |
1369 | bat_destroy(b); |
1370 | if (bat->ibid == BID_NIL) |
1371 | return LOG_ERR; |
1372 | i = temp_descriptor(bat->ibid); |
1373 | if (i == NULL) |
1374 | return LOG_ERR; |
1375 | bat_set_access(i, BAT_READ); |
1376 | BAThseqbase(i, bat->ibase); |
1377 | bat_destroy(i); |
1378 | } else { |
1379 | BAT *i, *b = temp_descriptor(bat->ibid); |
1380 | int type; |
1381 | |
1382 | if (b == NULL) |
1383 | return LOG_ERR; |
1384 | type = b->ttype; |
1385 | bat->bid = bat->ibid; |
1386 | bat->cnt = bat->ibase = BATcount(b); |
1387 | bat->ucnt = 0; |
1388 | bat_destroy(b); |
1389 | |
1390 | i = COLnew(bat->ibase, type, sz, PERSISTENT); |
1391 | if (i == NULL) |
1392 | return LOG_ERR; |
1393 | bat_set_access(i, BAT_READ); |
1394 | bat->ibid = temp_create(i); |
1395 | bat_destroy(i); |
1396 | } |
1397 | return LOG_OK; |
1398 | } |
1399 | |
1400 | static int |
1401 | new_persistent_bat(sql_trans *tr, sql_delta *bat, int sz) |
1402 | { |
1403 | (void)tr; |
1404 | return new_persistent_delta(bat, sz); |
1405 | } |
1406 | |
1407 | static void |
1408 | create_delta( sql_delta *d, BAT *b, BAT *i) |
1409 | { |
1410 | d->cnt = BATcount(i); |
1411 | bat_set_access(i, BAT_READ); |
1412 | d->bid = 0; |
1413 | d->ibase = i->hseqbase; |
1414 | d->ibid = temp_create(i); |
1415 | if (b) { |
1416 | d->cnt += BATcount(b); |
1417 | bat_set_access(b, BAT_READ); |
1418 | d->bid = temp_create(b); |
1419 | } |
1420 | d->uibid = d->uvbid = 0; |
1421 | d->ucnt = 0; |
1422 | } |
1423 | |
1424 | static int |
1425 | upgrade_delta( sql_delta *d, char tpe, oid id) |
1426 | { |
1427 | return logger_upgrade_bat(bat_logger, d->name, tpe, id) == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
1428 | } |
1429 | |
1430 | static bat |
1431 | copyBat (bat i, int type, oid seq) |
1432 | { |
1433 | BAT *b, *tb; |
1434 | bat res; |
1435 | |
1436 | if (!i) |
1437 | return i; |
1438 | tb = temp_descriptor(i); |
1439 | if (tb == NULL) |
1440 | return 0; |
1441 | b = BATconstant(seq, type, ATOMnilptr(type), BATcount(tb), PERSISTENT); |
1442 | bat_destroy(tb); |
1443 | if (b == NULL) |
1444 | return 0; |
1445 | |
1446 | bat_set_access(b, BAT_READ); |
1447 | |
1448 | res = temp_create(b); |
1449 | bat_destroy(b); |
1450 | return res; |
1451 | } |
1452 | |
1453 | static int |
1454 | create_col(sql_trans *tr, sql_column *c) |
1455 | { |
1456 | int ok = LOG_OK; |
1457 | int type = c->type.type->localtype; |
1458 | sql_delta *bat = c->data; |
1459 | |
1460 | if (!bat || !c->base.allocated) { |
1461 | c->data = bat = ZNEW(sql_delta); |
1462 | if(!bat) |
1463 | return LOG_ERR; |
1464 | bat->wtime = c->base.wtime = tr->wstime; |
1465 | c->base.allocated = 1; |
1466 | } |
1467 | if (!bat->name) { |
1468 | bat->name = sql_message("%s_%s_%s" , c->t->s->base.name, c->t->base.name, c->base.name); |
1469 | if(!bat->name) |
1470 | ok = LOG_ERR; |
1471 | } |
1472 | |
1473 | if (!isNew(c) && !isTempTable(c->t)){ |
1474 | c->base.wtime = 0; |
1475 | return load_bat(bat, type, c->t->bootstrap?0:LOG_COL, c->base.id); |
1476 | } else if (bat && bat->ibid && !isTempTable(c->t)) { |
1477 | return new_persistent_bat(tr, c->data, c->t->sz); |
1478 | } else if (!bat->ibid) { |
1479 | sql_column *fc = NULL; |
1480 | size_t cnt = 0; |
1481 | |
1482 | /* alter ? */ |
1483 | if (c->t->columns.set && (fc = c->t->columns.set->h->data) != NULL) |
1484 | cnt = count_col(tr, fc, 1); |
1485 | if (cnt && fc != c) { |
1486 | sql_delta *d = fc->data; |
1487 | |
1488 | if (d->bid) { |
1489 | bat->bid = copyBat(d->bid, type, 0); |
1490 | if(bat->bid == BID_NIL) |
1491 | ok = LOG_ERR; |
1492 | } |
1493 | if (d->ibid) { |
1494 | bat->ibid = copyBat(d->ibid, type, d->ibase); |
1495 | if(bat->ibid == BID_NIL) |
1496 | ok = LOG_ERR; |
1497 | } |
1498 | bat->ibase = d->ibase; |
1499 | bat->cnt = d->cnt; |
1500 | if (d->uibid) { |
1501 | bat->uibid = e_bat(TYPE_oid); |
1502 | if (bat->uibid == BID_NIL) |
1503 | ok = LOG_ERR; |
1504 | } |
1505 | if (d->uvbid) { |
1506 | bat->uvbid = e_bat(type); |
1507 | if(bat->uvbid == BID_NIL) |
1508 | ok = LOG_ERR; |
1509 | } |
1510 | } else { |
1511 | BAT *b = bat_new(type, c->t->sz, PERSISTENT); |
1512 | if (!b) { |
1513 | ok = LOG_ERR; |
1514 | } else { |
1515 | create_delta(c->data, NULL, b); |
1516 | bat_destroy(b); |
1517 | } |
1518 | } |
1519 | } |
1520 | return ok; |
1521 | } |
1522 | |
1523 | static int |
1524 | upgrade_col(sql_column *c) |
1525 | { |
1526 | sql_delta *bat = c->data; |
1527 | |
1528 | if (!c->t->bootstrap) |
1529 | return upgrade_delta(bat, LOG_COL, c->base.id); |
1530 | return LOG_OK; |
1531 | } |
1532 | |
1533 | static int |
1534 | log_create_col(sql_trans *tr, sql_column *c) |
1535 | { |
1536 | (void)tr; |
1537 | assert(tr->parent == gtrans && !isTempTable(c->t)); |
1538 | return log_create_delta( c->data, c->t->bootstrap?0:LOG_COL, c->base.id); |
1539 | } |
1540 | |
1541 | static int |
1542 | snapshot_create_col(sql_trans *tr, sql_column *c) |
1543 | { |
1544 | (void)tr; |
1545 | assert(tr->parent == gtrans && !isTempTable(c->t)); |
1546 | return snapshot_new_persistent_bat( tr, c->data); |
1547 | } |
1548 | |
1549 | /* will be called for new idx's and when new index columns are created */ |
1550 | static int |
1551 | create_idx(sql_trans *tr, sql_idx *ni) |
1552 | { |
1553 | int ok = LOG_OK; |
1554 | sql_delta *bat = ni->data; |
1555 | int type = TYPE_lng; |
1556 | |
1557 | if (oid_index(ni->type)) |
1558 | type = TYPE_oid; |
1559 | |
1560 | if (!bat || !ni->base.allocated) { |
1561 | ni->data = bat = ZNEW(sql_delta); |
1562 | if(!bat) |
1563 | return LOG_ERR; |
1564 | bat->wtime = ni->base.wtime = tr->wstime; |
1565 | ni->base.allocated = 1; |
1566 | } |
1567 | if (!bat->name) { |
1568 | bat->name = sql_message("%s_%s@%s" , ni->t->s->base.name, ni->t->base.name, ni->base.name); |
1569 | if(!bat->name) |
1570 | ok = LOG_ERR; |
1571 | } |
1572 | |
1573 | if (!isNew(ni) && !isTempTable(ni->t)){ |
1574 | ni->base.wtime = 0; |
1575 | return load_bat(bat, type, ni->t->bootstrap?0:LOG_IDX, ni->base.id); |
1576 | } else if (bat && bat->ibid && !isTempTable(ni->t)) { |
1577 | return new_persistent_bat( tr, ni->data, ni->t->sz); |
1578 | } else if (!bat->ibid) { |
1579 | sql_column *c = ni->t->columns.set->h->data; |
1580 | sql_delta *d; |
1581 | |
1582 | if (!c->data) { |
1583 | sql_column *oc = tr_find_column(tr->parent, c); |
1584 | c->data = timestamp_delta(oc->data, c->base.stime); |
1585 | } |
1586 | d = c->data; |
1587 | /* Here we also handle indices created through alter stmts */ |
1588 | /* These need to be created aligned to the existing data */ |
1589 | |
1590 | |
1591 | if (d->bid) { |
1592 | bat->bid = copyBat(d->bid, type, 0); |
1593 | if(bat->bid == BID_NIL) |
1594 | ok = LOG_ERR; |
1595 | } |
1596 | if (d->ibid) { |
1597 | bat->ibid = copyBat(d->ibid, type, d->ibase); |
1598 | if(bat->ibid == BID_NIL) |
1599 | ok = LOG_ERR; |
1600 | } |
1601 | bat->ibase = d->ibase; |
1602 | bat->cnt = d->cnt; |
1603 | bat->ucnt = 0; |
1604 | |
1605 | if (d->uibid) { |
1606 | bat->uibid = e_bat(TYPE_oid); |
1607 | if (bat->uibid == BID_NIL) |
1608 | ok = LOG_ERR; |
1609 | } |
1610 | if (d->uvbid) { |
1611 | bat->uvbid = e_bat(type); |
1612 | if(bat->uvbid == BID_NIL) |
1613 | ok = LOG_ERR; |
1614 | } |
1615 | } |
1616 | return ok; |
1617 | } |
1618 | |
1619 | static int |
1620 | upgrade_idx(sql_idx *i) |
1621 | { |
1622 | sql_delta *bat = i->data; |
1623 | |
1624 | if (!i->t->bootstrap && bat != NULL) |
1625 | return upgrade_delta(bat, LOG_IDX, i->base.id); |
1626 | return LOG_OK; |
1627 | } |
1628 | |
1629 | static int |
1630 | log_create_idx(sql_trans *tr, sql_idx *ni) |
1631 | { |
1632 | (void)tr; |
1633 | assert(tr->parent == gtrans && !isTempTable(ni->t)); |
1634 | return log_create_delta( ni->data, ni->t->bootstrap?0:LOG_IDX, ni->base.id); |
1635 | } |
1636 | |
1637 | static int |
1638 | snapshot_create_idx(sql_trans *tr, sql_idx *ni) |
1639 | { |
1640 | assert(tr->parent == gtrans && !isTempTable(ni->t)); |
1641 | return snapshot_new_persistent_bat( tr, ni->data); |
1642 | } |
1643 | |
1644 | static int |
1645 | load_dbat(sql_dbat *bat, int bid) |
1646 | { |
1647 | BAT *b = quick_descriptor(bid); |
1648 | if(b) { |
1649 | bat->dbid = temp_create(b); |
1650 | bat->cnt = BATcount(b); |
1651 | return LOG_OK; |
1652 | } else { |
1653 | return LOG_ERR; |
1654 | } |
1655 | } |
1656 | |
1657 | static int |
1658 | create_del(sql_trans *tr, sql_table *t) |
1659 | { |
1660 | int ok = LOG_OK; |
1661 | BAT *b; |
1662 | sql_dbat *bat = t->data; |
1663 | |
1664 | if (!bat) { |
1665 | t->data = bat = ZNEW(sql_dbat); |
1666 | if(!bat) |
1667 | return LOG_ERR; |
1668 | bat->wtime = t->base.wtime = t->s->base.wtime = tr->wstime; |
1669 | t->base.allocated = 1; |
1670 | } |
1671 | if (!bat->dname) { |
1672 | bat->dname = sql_message("D_%s_%s" , t->s->base.name, t->base.name); |
1673 | if(!bat->dname) |
1674 | ok = LOG_ERR; |
1675 | } |
1676 | (void)tr; |
1677 | if (!isNew(t) && !isTempTable(t)) { |
1678 | log_bid bid = logger_find_bat(bat_logger, bat->dname, t->bootstrap?0:LOG_TAB, t->base.id); |
1679 | |
1680 | if (bid) { |
1681 | t->base.wtime = 0; |
1682 | return load_dbat(bat, bid); |
1683 | } |
1684 | ok = LOG_ERR; |
1685 | } else if (bat->dbid && !isTempTable(t)) { |
1686 | return ok; |
1687 | } else if (!bat->dbid) { |
1688 | b = bat_new(TYPE_oid, t->sz, PERSISTENT); |
1689 | if(b != NULL) { |
1690 | bat_set_access(b, BAT_READ); |
1691 | bat->dbid = temp_create(b); |
1692 | bat_destroy(b); |
1693 | } else { |
1694 | ok = LOG_ERR; |
1695 | } |
1696 | } |
1697 | return ok; |
1698 | } |
1699 | |
1700 | static int |
1701 | upgrade_del(sql_table *t) |
1702 | { |
1703 | sql_dbat *bat = t->data; |
1704 | |
1705 | if (!t->bootstrap) |
1706 | return logger_upgrade_bat(bat_logger, bat->dname, LOG_TAB, t->base.id) == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
1707 | return LOG_OK; |
1708 | } |
1709 | |
1710 | static int |
1711 | log_create_dbat( sql_dbat *bat, char tpe, oid id) |
1712 | { |
1713 | BAT *b; |
1714 | gdk_return ok; |
1715 | |
1716 | if (GDKinmemory()) |
1717 | return LOG_OK; |
1718 | |
1719 | b = temp_descriptor(bat->dbid); |
1720 | if (b == NULL) |
1721 | return LOG_ERR; |
1722 | |
1723 | ok = logger_add_bat(bat_logger, b, bat->dname, tpe, id); |
1724 | if (ok == GDK_SUCCEED) |
1725 | ok = log_bat_persists(bat_logger, b, bat->dname, tpe, id); |
1726 | bat_destroy(b); |
1727 | return ok == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
1728 | } |
1729 | |
1730 | static int |
1731 | log_create_del(sql_trans *tr, sql_table *t) |
1732 | { |
1733 | (void)tr; |
1734 | assert(tr->parent == gtrans && !isTempTable(t)); |
1735 | return log_create_dbat(t->data, t->bootstrap?0:LOG_TAB, t->base.id); |
1736 | } |
1737 | |
1738 | static int |
1739 | snapshot_create_del(sql_trans *tr, sql_table *t) |
1740 | { |
1741 | sql_dbat *bat = t->data; |
1742 | BAT *b = temp_descriptor(bat->dbid); |
1743 | |
1744 | if (b == NULL) |
1745 | return LOG_ERR; |
1746 | |
1747 | (void)tr; |
1748 | /* snapshot large bats */ |
1749 | bat_set_access(b, BAT_READ); |
1750 | if (BATcount(b) > SNAPSHOT_MINSIZE) |
1751 | BATmode(b, false); |
1752 | bat_destroy(b); |
1753 | return LOG_OK; |
1754 | } |
1755 | |
1756 | static int |
1757 | log_destroy_delta(sql_trans *tr, sql_delta *b, char tpe, oid id) |
1758 | { |
1759 | log_bid bid; |
1760 | gdk_return ok = GDK_SUCCEED; |
1761 | |
1762 | (void)tr; |
1763 | if (!GDKinmemory() && |
1764 | b && |
1765 | b->bid && |
1766 | b->name && |
1767 | (ok = log_bat_transient(bat_logger, b->name, tpe, id)) == GDK_SUCCEED && |
1768 | (bid = logger_find_bat(bat_logger, b->name, tpe, id)) != 0) { |
1769 | ok = logger_del_bat(bat_logger, bid); |
1770 | } |
1771 | return ok == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
1772 | } |
1773 | |
1774 | static int |
1775 | destroy_delta(sql_delta *b) |
1776 | { |
1777 | if (b->name) |
1778 | _DELETE(b->name); |
1779 | if (b->ibid) |
1780 | temp_destroy(b->ibid); |
1781 | if (b->uibid) |
1782 | temp_destroy(b->uibid); |
1783 | if (b->uvbid) |
1784 | temp_destroy(b->uvbid); |
1785 | if (b->bid) |
1786 | temp_destroy(b->bid); |
1787 | if (b->cached) |
1788 | bat_destroy(b->cached); |
1789 | b->bid = b->ibid = b->uibid = b->uvbid = 0; |
1790 | b->name = NULL; |
1791 | b->cached = NULL; |
1792 | return LOG_OK; |
1793 | } |
1794 | |
1795 | static int |
1796 | destroy_bat(sql_delta *b) |
1797 | { |
1798 | sql_delta *n; |
1799 | |
1800 | while(b) { |
1801 | n = b->next; |
1802 | destroy_delta(b); |
1803 | _DELETE(b); |
1804 | b = n; |
1805 | } |
1806 | return LOG_OK; |
1807 | } |
1808 | |
1809 | static int |
1810 | destroy_col(sql_trans *tr, sql_column *c) |
1811 | { |
1812 | int ok = LOG_OK; |
1813 | |
1814 | (void)tr; |
1815 | if (c->data && c->base.allocated) { |
1816 | c->base.allocated = 0; |
1817 | ok = destroy_bat(c->data); |
1818 | } |
1819 | c->data = NULL; |
1820 | return ok; |
1821 | } |
1822 | |
1823 | static int |
1824 | log_destroy_col(sql_trans *tr, sql_column *c) |
1825 | { |
1826 | if (c->data && c->base.allocated) |
1827 | return log_destroy_delta(tr, c->data, c->t->bootstrap?0:LOG_COL, c->base.id); |
1828 | return LOG_OK; |
1829 | } |
1830 | |
1831 | static int |
1832 | destroy_idx(sql_trans *tr, sql_idx *i) |
1833 | { |
1834 | int ok = LOG_OK; |
1835 | |
1836 | (void)tr; |
1837 | if (i->data && i->base.allocated) { |
1838 | i->base.allocated = 0; |
1839 | ok = destroy_bat(i->data); |
1840 | } |
1841 | i->data = NULL; |
1842 | return ok; |
1843 | } |
1844 | |
1845 | static int |
1846 | log_destroy_idx(sql_trans *tr, sql_idx *i) |
1847 | { |
1848 | if (i->data && i->base.allocated) |
1849 | return log_destroy_delta(tr, i->data, i->t->bootstrap?0:LOG_IDX, i->base.id); |
1850 | return LOG_OK; |
1851 | } |
1852 | |
1853 | static void |
1854 | _destroy_dbat(sql_dbat *bat) |
1855 | { |
1856 | if (bat->dname) |
1857 | _DELETE(bat->dname); |
1858 | if (bat->dbid) |
1859 | temp_destroy(bat->dbid); |
1860 | if (bat->cached) { |
1861 | bat_destroy(bat->cached); |
1862 | bat->cached = NULL; |
1863 | } |
1864 | bat->dbid = 0; |
1865 | bat->dname = NULL; |
1866 | _DELETE(bat); |
1867 | } |
1868 | |
1869 | static int |
1870 | destroy_dbat(sql_trans *tr, sql_dbat *bat) |
1871 | { |
1872 | sql_dbat *n; |
1873 | |
1874 | (void)tr; |
1875 | while(bat) { |
1876 | n = bat->next; |
1877 | _destroy_dbat(bat); |
1878 | bat = n; |
1879 | } |
1880 | return LOG_OK; |
1881 | } |
1882 | |
1883 | static int |
1884 | cleanup(void) |
1885 | { |
1886 | int ok = LOG_OK; |
1887 | |
1888 | MT_lock_set(&destroy_lock); |
1889 | if (tobe_destroyed_delta) { |
1890 | ok = destroy_bat(tobe_destroyed_delta); |
1891 | tobe_destroyed_delta = NULL; |
1892 | } |
1893 | if (ok == LOG_OK && tobe_destroyed_dbat) { |
1894 | ok = destroy_dbat(NULL, tobe_destroyed_dbat); |
1895 | tobe_destroyed_dbat = NULL; |
1896 | } |
1897 | MT_lock_unset(&destroy_lock); |
1898 | return ok; |
1899 | } |
1900 | |
1901 | static int |
1902 | delayed_destroy_bat(sql_delta *b) |
1903 | { |
1904 | sql_delta *n = b; |
1905 | |
1906 | if (!n) |
1907 | return LOG_OK; |
1908 | while(n->next) |
1909 | n = n->next; |
1910 | MT_lock_set(&destroy_lock); |
1911 | n->next = tobe_destroyed_delta; |
1912 | tobe_destroyed_delta = b; |
1913 | MT_lock_unset(&destroy_lock); |
1914 | return LOG_OK; |
1915 | } |
1916 | |
1917 | static int |
1918 | delayed_destroy_dbat(sql_dbat *b) |
1919 | { |
1920 | sql_dbat *n = b; |
1921 | |
1922 | if (!n) |
1923 | return LOG_OK; |
1924 | while(n->next) |
1925 | n = n->next; |
1926 | MT_lock_set(&destroy_lock); |
1927 | n->next = tobe_destroyed_dbat; |
1928 | tobe_destroyed_dbat = b; |
1929 | MT_lock_unset(&destroy_lock); |
1930 | return LOG_OK; |
1931 | } |
1932 | |
1933 | static int |
1934 | destroy_del(sql_trans *tr, sql_table *t) |
1935 | { |
1936 | int ok = LOG_OK; |
1937 | |
1938 | if (t->data && t->base.allocated) { |
1939 | t->base.allocated = 0; |
1940 | ok = destroy_dbat(tr, t->data); |
1941 | } |
1942 | t->data = NULL; |
1943 | return ok; |
1944 | } |
1945 | |
1946 | static int |
1947 | log_destroy_dbat(sql_trans *tr, sql_dbat *bat, char tpe, oid id) |
1948 | { |
1949 | log_bid bid; |
1950 | gdk_return ok = GDK_SUCCEED; |
1951 | |
1952 | (void)tr; |
1953 | if (!GDKinmemory() && |
1954 | bat && |
1955 | bat->dbid && |
1956 | bat->dname && |
1957 | (ok = log_bat_transient(bat_logger, bat->dname, tpe, id)) == GDK_SUCCEED && |
1958 | (bid = logger_find_bat(bat_logger, bat->dname, tpe, id)) != 0) { |
1959 | ok = logger_del_bat(bat_logger, bid); |
1960 | } |
1961 | return ok == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
1962 | } |
1963 | |
1964 | static int |
1965 | log_destroy_del(sql_trans *tr, sql_table *t) |
1966 | { |
1967 | if (t->data && t->base.allocated) |
1968 | return log_destroy_dbat(tr, t->data, t->bootstrap?0:LOG_TAB, t->base.id); |
1969 | return LOG_OK; |
1970 | } |
1971 | |
1972 | static BUN |
1973 | clear_delta(sql_trans *tr, sql_delta *bat) |
1974 | { |
1975 | BAT *b; |
1976 | BUN sz = 0; |
1977 | |
1978 | if (bat->cached) { |
1979 | bat_destroy(bat->cached); |
1980 | bat->cached = NULL; |
1981 | } |
1982 | if (bat->ibid) { |
1983 | b = temp_descriptor(bat->ibid); |
1984 | if (b && !isEbat(b)) { |
1985 | sz += BATcount(b); |
1986 | bat_clear(b); |
1987 | BATcommit(b); |
1988 | } |
1989 | if (b) |
1990 | bat_destroy(b); |
1991 | } |
1992 | if (bat->bid) { |
1993 | b = temp_descriptor(bat->bid); |
1994 | if (b) { |
1995 | assert(!isEbat(b)); |
1996 | sz += BATcount(b); |
1997 | /* for transactions we simple switch to ibid only */ |
1998 | if (tr != gtrans) { |
1999 | temp_destroy(bat->bid); |
2000 | bat->bid = 0; |
2001 | } else { |
2002 | bat_clear(b); |
2003 | BATcommit(b); |
2004 | } |
2005 | bat_destroy(b); |
2006 | } |
2007 | } |
2008 | if (bat->uibid) { |
2009 | b = temp_descriptor(bat->uibid); |
2010 | if (b && !isEbat(b)) { |
2011 | bat_clear(b); |
2012 | BATcommit(b); |
2013 | } |
2014 | if (b) |
2015 | bat_destroy(b); |
2016 | } |
2017 | if (bat->uvbid) { |
2018 | b = temp_descriptor(bat->uvbid); |
2019 | if(b && !isEbat(b)) { |
2020 | bat_clear(b); |
2021 | BATcommit(b); |
2022 | } |
2023 | if (b) |
2024 | bat_destroy(b); |
2025 | } |
2026 | bat->cleared = 1; |
2027 | bat->ibase = 0; |
2028 | bat->cnt = 0; |
2029 | bat->ucnt = 0; |
2030 | bat->wtime = tr->wstime; |
2031 | return sz; |
2032 | } |
2033 | |
2034 | static BUN |
2035 | clear_col(sql_trans *tr, sql_column *c) |
2036 | { |
2037 | if (!c->data || !c->base.allocated) { |
2038 | int type = c->type.type->localtype; |
2039 | sql_column *oc = tr_find_column(tr->parent, c); |
2040 | sql_delta *bat = c->data = ZNEW(sql_delta), *obat; |
2041 | if(!bat) |
2042 | return 0; |
2043 | obat = timestamp_delta(oc->data, c->base.stime); |
2044 | assert(tr != gtrans); |
2045 | if(dup_bat(tr, c->t, obat, bat, type, isNew(oc), isNew(c)) == LOG_ERR) |
2046 | return 0; |
2047 | c->base.allocated = 1; |
2048 | } |
2049 | c->t->s->base.wtime = c->t->base.wtime = c->base.wtime = tr->wstime; |
2050 | if (c->data) |
2051 | return clear_delta(tr, c->data); |
2052 | return 0; |
2053 | } |
2054 | |
2055 | static BUN |
2056 | clear_idx(sql_trans *tr, sql_idx *i) |
2057 | { |
2058 | if (!isTable(i->t) || !idx_has_column(i->type)) |
2059 | return 0; |
2060 | if (!i->data || !i->base.allocated) { |
2061 | int type = (oid_index(i->type))?TYPE_oid:TYPE_lng; |
2062 | sql_idx *oi = tr_find_idx(tr->parent, i); |
2063 | sql_delta *bat = i->data = ZNEW(sql_delta), *obat; |
2064 | if(!bat) |
2065 | return 0; |
2066 | obat = timestamp_delta(oi->data, i->base.stime); |
2067 | if(dup_bat(tr, i->t, obat, bat, type, isNew(i), isNew(i))) |
2068 | return 0; |
2069 | i->base.allocated = 1; |
2070 | } |
2071 | i->t->s->base.wtime = i->t->base.wtime = i->base.wtime = tr->wstime; |
2072 | if (i->data) |
2073 | return clear_delta(tr, i->data); |
2074 | return 0; |
2075 | } |
2076 | |
2077 | static BUN |
2078 | clear_dbat(sql_trans *tr, sql_dbat *bat) |
2079 | { |
2080 | BUN sz = 0; |
2081 | |
2082 | (void)tr; |
2083 | |
2084 | if (bat->cached) { |
2085 | bat_destroy(bat->cached); |
2086 | bat->cached = NULL; |
2087 | } |
2088 | if (bat->dbid) { |
2089 | BAT *b = temp_descriptor(bat->dbid); |
2090 | if(b && !isEbat(b)) { |
2091 | sz += BATcount(b); |
2092 | bat_clear(b); |
2093 | BATcommit(b); |
2094 | bat_destroy(b); |
2095 | } |
2096 | } |
2097 | bat->cleared = 1; |
2098 | bat->cnt = 0; |
2099 | bat->wtime = tr->wstime; |
2100 | return sz; |
2101 | } |
2102 | |
2103 | static BUN |
2104 | clear_del(sql_trans *tr, sql_table *t) |
2105 | { |
2106 | if (!t->data || !t->base.allocated) { |
2107 | sql_table *ot = tr_find_table(tr->parent, t); |
2108 | sql_dbat *bat = t->data = ZNEW(sql_dbat), *obat; |
2109 | if(!bat) |
2110 | return 0; |
2111 | obat = timestamp_dbat(ot->data, t->base.stime); |
2112 | dup_dbat(tr, obat, bat, isNew(ot), isTempTable(t)); |
2113 | t->base.allocated = 1; |
2114 | } |
2115 | t->s->base.wtime = t->base.wtime = tr->wstime; |
2116 | return clear_dbat(tr, t->data); |
2117 | } |
2118 | |
2119 | static int |
2120 | gtr_update_delta( sql_trans *tr, sql_delta *cbat, int *changes, int id, int tpe) |
2121 | { |
2122 | int ok = LOG_OK; |
2123 | BAT *ins, *cur; |
2124 | |
2125 | (void)tr; |
2126 | assert(ATOMIC_GET(&store_nr_active)==0); |
2127 | |
2128 | if (!cbat->bid) { |
2129 | cbat->bid = logger_find_bat(bat_logger, cbat->name, tpe, id); |
2130 | temp_dup(cbat->bid); |
2131 | } |
2132 | assert(cbat->bid == logger_find_bat(bat_logger, cbat->name, tpe, id)); |
2133 | cur = temp_descriptor(cbat->bid); |
2134 | ins = temp_descriptor(cbat->ibid); |
2135 | |
2136 | if(cur == NULL || ins == NULL) { |
2137 | bat_destroy(ins); |
2138 | bat_destroy(cur); |
2139 | return LOG_ERR; |
2140 | } |
2141 | assert(!isEbat(cur)); |
2142 | /* any inserts */ |
2143 | if (BUNlast(ins) > 0 || cbat->cleared) { |
2144 | (*changes)++; |
2145 | assert(cur->theap.storage != STORE_PRIV); |
2146 | if (cbat->cleared) |
2147 | bat_clear(cur); |
2148 | if (BATappend(cur, ins, NULL, true) != GDK_SUCCEED) { |
2149 | bat_destroy(ins); |
2150 | bat_destroy(cur); |
2151 | return LOG_ERR; |
2152 | } |
2153 | cbat->cnt = cbat->ibase = BATcount(cur); |
2154 | temp_destroy(cbat->ibid); |
2155 | cbat->ibid = e_bat(cur->ttype); |
2156 | if(cbat->ibid == BID_NIL) |
2157 | ok = LOG_ERR; |
2158 | } |
2159 | bat_destroy(ins); |
2160 | |
2161 | if (cbat->ucnt) { |
2162 | BAT *ui = temp_descriptor(cbat->uibid); |
2163 | BAT *uv = temp_descriptor(cbat->uvbid); |
2164 | if(ui == NULL || uv == NULL) { |
2165 | bat_destroy(cur); |
2166 | return LOG_ERR; |
2167 | } |
2168 | /* any updates */ |
2169 | if (BUNlast(ui) > 0) { |
2170 | (*changes)++; |
2171 | if (void_replace_bat(cur, ui, uv, true) != GDK_SUCCEED) { |
2172 | bat_destroy(ui); |
2173 | bat_destroy(uv); |
2174 | bat_destroy(cur); |
2175 | return LOG_ERR; |
2176 | } |
2177 | temp_destroy(cbat->uibid); |
2178 | temp_destroy(cbat->uvbid); |
2179 | cbat->uibid = e_bat(TYPE_oid); |
2180 | cbat->uvbid = e_bat(cur->ttype); |
2181 | if(cbat->uibid == BID_NIL || cbat->uvbid == BID_NIL) |
2182 | ok = LOG_ERR; |
2183 | cbat->ucnt = 0; |
2184 | } |
2185 | bat_destroy(ui); |
2186 | bat_destroy(uv); |
2187 | } |
2188 | bat_destroy(cur); |
2189 | cbat->cleared = 0; |
2190 | if (cbat->next) { |
2191 | ok = destroy_bat(cbat->next); |
2192 | cbat->next = NULL; |
2193 | } |
2194 | return ok; |
2195 | } |
2196 | |
2197 | static int |
2198 | gtr_update_dbat(sql_trans *tr, sql_dbat *d, int *changes, char tpe, oid id) |
2199 | { |
2200 | int ok = LOG_OK; |
2201 | BAT *idb, *cdb; |
2202 | int dbid = logger_find_bat(bat_logger, d->dname, tpe, id); |
2203 | |
2204 | assert(ATOMIC_GET(&store_nr_active)==0); |
2205 | if (d->dbid == dbid) { |
2206 | /* if set its handled by the bat clear of the dbid */ |
2207 | d->cleared = 0; |
2208 | if (d->next) { |
2209 | ok = destroy_dbat(tr, d->next); |
2210 | d->next = NULL; |
2211 | } |
2212 | return ok; |
2213 | } |
2214 | idb = temp_descriptor(d->dbid); |
2215 | if(!idb) |
2216 | return LOG_ERR; |
2217 | cdb = temp_descriptor(dbid); |
2218 | if(cdb) { |
2219 | (*changes)++; |
2220 | assert(!isEbat(cdb)); |
2221 | if (d->cleared) { |
2222 | bat_clear(cdb); |
2223 | d->cnt = 0; |
2224 | } |
2225 | d->cnt = BATcount(cdb); |
2226 | idb->batInserted = d->cnt; |
2227 | if (append_inserted(cdb, idb) == BUN_NONE) |
2228 | ok = LOG_ERR; |
2229 | else |
2230 | BATcommit(cdb); |
2231 | d->cnt = BATcount(cdb); |
2232 | bat_destroy(cdb); |
2233 | } else { |
2234 | ok = LOG_ERR; |
2235 | } |
2236 | assert(BATcount(quick_descriptor(dbid)) == d->cnt); |
2237 | d->cleared = 0; |
2238 | temp_destroy(d->dbid); |
2239 | d->dbid = dbid; |
2240 | temp_dup(d->dbid); |
2241 | bat_destroy(idb); |
2242 | assert(BATcount(quick_descriptor(d->dbid)) == d->cnt); |
2243 | return ok; |
2244 | } |
2245 | |
2246 | static int |
2247 | gtr_update_table(sql_trans *tr, sql_table *t, int *tchanges) |
2248 | { |
2249 | int ok = LOG_OK; |
2250 | node *n; |
2251 | |
2252 | if (t->base.wtime <= t->base.allocated) |
2253 | return ok; |
2254 | gtr_update_dbat(tr, t->data, tchanges, t->bootstrap?0:LOG_TAB, t->base.id); |
2255 | for (n = t->columns.set->h; ok == LOG_OK && n; n = n->next) { |
2256 | int changes = 0; |
2257 | sql_column *c = n->data; |
2258 | |
2259 | if (!c->base.wtime || c->base.wtime <= c->base.allocated) |
2260 | continue; |
2261 | ok = gtr_update_delta(tr, c->data, &changes, c->base.id, c->t->bootstrap?0:LOG_COL); |
2262 | if (changes) |
2263 | c->base.allocated = c->base.wtime = tr->wstime; |
2264 | (*tchanges) |= changes; |
2265 | } |
2266 | if (ok == LOG_OK && t->idxs.set) { |
2267 | for (n = t->idxs.set->h; ok == LOG_OK && n; n = n->next) { |
2268 | int changes = 0; |
2269 | sql_idx *ci = n->data; |
2270 | |
2271 | /* some indices have no bats */ |
2272 | if (!isTable(ci->t) || !idx_has_column(ci->type)) |
2273 | continue; |
2274 | if (!ci->base.wtime || ci->base.wtime <= ci->base.allocated) |
2275 | continue; |
2276 | |
2277 | ok = gtr_update_delta(tr, ci->data, &changes, ci->base.id, ci->t->bootstrap?0:LOG_IDX); |
2278 | if (changes) |
2279 | ci->base.allocated = ci->base.wtime = tr->wstime; |
2280 | (*tchanges) |= changes; |
2281 | } |
2282 | } |
2283 | if (*tchanges) |
2284 | t->base.allocated = t->base.wtime = tr->wstime; |
2285 | return ok; |
2286 | } |
2287 | |
2288 | typedef int (*gtr_update_table_fptr)( sql_trans *tr, sql_table *t, int *changes); |
2289 | |
2290 | static int |
2291 | _gtr_update( sql_trans *tr, gtr_update_table_fptr gtr_update_table_f) |
2292 | { |
2293 | int ok = LOG_OK, tchanges = 0; |
2294 | node *sn; |
2295 | |
2296 | for(sn = tr->schemas.set->h; sn && ok == LOG_OK; sn = sn->next) { |
2297 | int schanges = 0; |
2298 | sql_schema *s = sn->data; |
2299 | |
2300 | if (s->base.wtime <= s->base.allocated && |
2301 | gtr_update_table_f == gtr_update_table) |
2302 | continue; |
2303 | if (!s->base.wtime) |
2304 | continue; |
2305 | if (!isTempSchema(s) && s->tables.set) { |
2306 | node *n; |
2307 | for (n = s->tables.set->h; n && ok == LOG_OK; n = n->next) { |
2308 | int changes = 0; |
2309 | sql_table *t = n->data; |
2310 | |
2311 | if (isTable(t) && isGlobal(t)) |
2312 | ok = gtr_update_table_f(tr, t, &changes); |
2313 | schanges |= changes; |
2314 | } |
2315 | } |
2316 | if (schanges && gtr_update_table_f == gtr_update_table){ |
2317 | s->base.allocated = s->base.wtime = tr->wstime; |
2318 | tchanges ++; |
2319 | } |
2320 | } |
2321 | if (tchanges && gtr_update_table_f == gtr_update_table) |
2322 | tr->wtime = tr->wstime; |
2323 | return LOG_OK; |
2324 | } |
2325 | |
2326 | static int |
2327 | gtr_update( sql_trans *tr ) |
2328 | { |
2329 | return _gtr_update(tr, >r_update_table); |
2330 | } |
2331 | |
2332 | static int |
2333 | gtr_minmax_col( sql_trans *tr, sql_column *c) |
2334 | { |
2335 | int ok = LOG_OK; |
2336 | sql_delta *cbat = c->data; |
2337 | BAT *cur; |
2338 | lng val; |
2339 | |
2340 | (void)tr; |
2341 | /* already set */ |
2342 | if (!cbat || c->type.type->localtype >= TYPE_str || c->t->system) |
2343 | return ok; |
2344 | |
2345 | cur = temp_descriptor(cbat->bid); |
2346 | if (cur == NULL) |
2347 | return LOG_ERR; |
2348 | /* make sure min and max values are stored in the BAT |
2349 | * properties (BATmin and BATmax store them there if they're |
2350 | * not already there, and if they are, they're quick) */ |
2351 | BATmin(cur, &val); |
2352 | BATmax(cur, &val); |
2353 | bat_destroy(cur); |
2354 | return ok; |
2355 | } |
2356 | |
2357 | static int |
2358 | gtr_minmax_table(sql_trans *tr, sql_table *t, int *changes) |
2359 | { |
2360 | int ok = LOG_OK; |
2361 | node *n; |
2362 | |
2363 | (void)changes; |
2364 | if (t->access > TABLE_WRITABLE) { |
2365 | for (n = t->columns.set->h; ok == LOG_OK && n; n = n->next) { |
2366 | sql_column *c = n->data; |
2367 | |
2368 | ok = gtr_minmax_col(tr, c); |
2369 | } |
2370 | } |
2371 | return ok; |
2372 | } |
2373 | |
2374 | static int |
2375 | gtr_minmax( sql_trans *tr ) |
2376 | { |
2377 | return _gtr_update(tr, >r_minmax_table); |
2378 | } |
2379 | |
2380 | static int |
2381 | tr_update_delta( sql_trans *tr, sql_delta *obat, sql_delta *cbat, int unique) |
2382 | { |
2383 | int ok = LOG_OK; |
2384 | BAT *ins, *cur = NULL; |
2385 | |
2386 | (void)tr; |
2387 | assert(ATOMIC_GET(&store_nr_active)==1); |
2388 | assert (obat->bid != 0 || tr != gtrans); |
2389 | |
2390 | /* for cleared tables the bid is reset */ |
2391 | if (cbat->bid == 0) { |
2392 | cbat->bid = obat->bid; |
2393 | if (cbat->bid) |
2394 | temp_dup(cbat->bid); |
2395 | } |
2396 | |
2397 | if (obat->cached) { |
2398 | bat_destroy(obat->cached); |
2399 | obat->cached = NULL; |
2400 | } |
2401 | if (cbat->cached) { |
2402 | bat_destroy(cbat->cached); |
2403 | cbat->cached = NULL; |
2404 | } |
2405 | if (obat->bid) { |
2406 | cur = temp_descriptor(obat->bid); |
2407 | if(!cur) |
2408 | return LOG_ERR; |
2409 | } |
2410 | if (!obat->bid && tr != gtrans) { |
2411 | if (obat->next) |
2412 | destroy_bat(obat->next); |
2413 | destroy_delta(obat); |
2414 | *obat = *cbat; |
2415 | cbat->bid = 0; |
2416 | cbat->ibid = 0; |
2417 | cbat->uibid = 0; |
2418 | cbat->uvbid = 0; |
2419 | cbat->cleared = 0; |
2420 | cbat->name = NULL; |
2421 | cbat->cached = NULL; |
2422 | return ok; |
2423 | } |
2424 | ins = temp_descriptor(cbat->ibid); |
2425 | if(!ins) { |
2426 | bat_destroy(cur); |
2427 | return LOG_ERR; |
2428 | } |
2429 | /* any inserts */ |
2430 | if (BUNlast(ins) > 0 || cbat->cleared) { |
2431 | if ((!obat->ibase && BATcount(ins) > SNAPSHOT_MINSIZE)){ |
2432 | /* swap cur and ins */ |
2433 | BAT *newcur = ins; |
2434 | |
2435 | if (unique) |
2436 | BATkey(newcur, true); |
2437 | temp_destroy(cbat->bid); |
2438 | temp_destroy(obat->bid); |
2439 | obat->bid = cbat->ibid; |
2440 | cbat->bid = cbat->ibid = 0; |
2441 | |
2442 | BATmsync(ins); |
2443 | ins = cur; |
2444 | cur = newcur; |
2445 | } else { |
2446 | assert(cur->theap.storage != STORE_PRIV); |
2447 | assert(!BATcount(ins) || !isEbat(ins)); |
2448 | assert(!isEbat(cur)); |
2449 | if (cbat->cleared) |
2450 | bat_clear(cur); |
2451 | if (BATappend(cur, ins, NULL, true) != GDK_SUCCEED) { |
2452 | bat_destroy(cur); |
2453 | bat_destroy(ins); |
2454 | return LOG_ERR; |
2455 | } |
2456 | temp_destroy(cbat->bid); |
2457 | temp_destroy(cbat->ibid); |
2458 | cbat->bid = cbat->ibid = 0; |
2459 | } |
2460 | obat->cnt = cbat->cnt = obat->ibase = cbat->ibase = BATcount(cur); |
2461 | temp_destroy(obat->ibid); |
2462 | obat->ibid = e_bat(cur->ttype); |
2463 | if (obat->ibid == BID_NIL) |
2464 | ok = LOG_ERR; |
2465 | } |
2466 | if (obat->cnt != cbat->cnt) { /* locked */ |
2467 | obat->cnt = cbat->cnt; |
2468 | obat->ibase = cbat->ibase; |
2469 | } |
2470 | bat_destroy(ins); |
2471 | |
2472 | if (cbat->ucnt && cbat->uibid) { |
2473 | BAT *ui = temp_descriptor(cbat->uibid); |
2474 | BAT *uv = temp_descriptor(cbat->uvbid); |
2475 | if(!ui || !uv) { |
2476 | bat_destroy(ui); |
2477 | bat_destroy(uv); |
2478 | bat_destroy(cur); |
2479 | return LOG_ERR; |
2480 | } |
2481 | |
2482 | /* any updates */ |
2483 | assert(!isEbat(cur)); |
2484 | if (BUNlast(ui) > 0) { |
2485 | if (void_replace_bat(cur, ui, uv, true) != GDK_SUCCEED) { |
2486 | bat_destroy(ui); |
2487 | bat_destroy(uv); |
2488 | bat_destroy(cur); |
2489 | return LOG_ERR; |
2490 | } |
2491 | /* cleanup the old deltas */ |
2492 | temp_destroy(obat->uibid); |
2493 | temp_destroy(obat->uvbid); |
2494 | obat->uibid = e_bat(TYPE_oid); |
2495 | obat->uvbid = e_bat(cur->ttype); |
2496 | if(obat->uibid == BID_NIL || obat->uvbid == BID_NIL) |
2497 | ok = LOG_ERR; |
2498 | temp_destroy(cbat->uibid); |
2499 | temp_destroy(cbat->uvbid); |
2500 | cbat->uibid = cbat->uvbid = 0; |
2501 | cbat->ucnt = obat->ucnt = 0; |
2502 | } |
2503 | bat_destroy(ui); |
2504 | bat_destroy(uv); |
2505 | } |
2506 | bat_destroy(cur); |
2507 | if (obat->next) { |
2508 | ok = destroy_bat(obat->next); |
2509 | obat->next = NULL; |
2510 | } |
2511 | return ok; |
2512 | } |
2513 | |
2514 | static int |
2515 | tr_merge_delta( sql_trans *tr, sql_delta *obat, int unique) |
2516 | { |
2517 | int ok = LOG_OK; |
2518 | BAT *ins, *cur = NULL; |
2519 | |
2520 | (void)tr; |
2521 | assert(ATOMIC_GET(&store_nr_active)==1); |
2522 | assert (obat->bid != 0 || tr != gtrans); |
2523 | |
2524 | assert(!obat->cleared); |
2525 | if (obat->cached) { |
2526 | bat_destroy(obat->cached); |
2527 | obat->cached = NULL; |
2528 | } |
2529 | if (obat->bid) { |
2530 | cur = temp_descriptor(obat->bid); |
2531 | if(!cur) |
2532 | return LOG_ERR; |
2533 | } |
2534 | ins = temp_descriptor(obat->ibid); |
2535 | if(!ins) { |
2536 | bat_destroy(cur); |
2537 | return LOG_ERR; |
2538 | } |
2539 | /* any inserts */ |
2540 | if (BUNlast(ins) > 0) { |
2541 | if ((!obat->ibase && BATcount(ins) > SNAPSHOT_MINSIZE)){ |
2542 | /* swap cur and ins */ |
2543 | BAT *newcur = ins; |
2544 | bat id = obat->bid; |
2545 | |
2546 | if (unique) |
2547 | BATkey(newcur, true); |
2548 | obat->bid = obat->ibid; |
2549 | obat->ibid = id; |
2550 | |
2551 | BATmsync(ins); |
2552 | ins = cur; |
2553 | cur = newcur; |
2554 | } else { |
2555 | assert(!isEbat(cur)); |
2556 | if (BATappend(cur, ins, NULL, true) != GDK_SUCCEED) { |
2557 | bat_destroy(cur); |
2558 | bat_destroy(ins); |
2559 | return LOG_ERR; |
2560 | } |
2561 | } |
2562 | obat->cnt = obat->ibase = BATcount(cur); |
2563 | temp_destroy(obat->ibid); |
2564 | obat->ibid = e_bat(cur->ttype); |
2565 | if (obat->ibid == BID_NIL) |
2566 | ok = LOG_ERR; |
2567 | } |
2568 | bat_destroy(ins); |
2569 | |
2570 | if (obat->ucnt) { |
2571 | BAT *ui = temp_descriptor(obat->uibid); |
2572 | BAT *uv = temp_descriptor(obat->uvbid); |
2573 | |
2574 | if(!ui || !uv) { |
2575 | bat_destroy(ui); |
2576 | bat_destroy(uv); |
2577 | bat_destroy(cur); |
2578 | return LOG_ERR; |
2579 | } |
2580 | |
2581 | /* any updates */ |
2582 | assert(!isEbat(cur)); |
2583 | if (BUNlast(ui) > 0) { |
2584 | if (void_replace_bat(cur, ui, uv, true) != GDK_SUCCEED) { |
2585 | bat_destroy(ui); |
2586 | bat_destroy(uv); |
2587 | bat_destroy(cur); |
2588 | return LOG_ERR; |
2589 | } |
2590 | /* cleanup the old deltas */ |
2591 | temp_destroy(obat->uibid); |
2592 | temp_destroy(obat->uvbid); |
2593 | obat->uibid = e_bat(TYPE_oid); |
2594 | obat->uvbid = e_bat(cur->ttype); |
2595 | if(obat->uibid == BID_NIL || obat->uvbid == BID_NIL) |
2596 | ok = LOG_ERR; |
2597 | obat->ucnt = 0; |
2598 | } |
2599 | bat_destroy(ui); |
2600 | bat_destroy(uv); |
2601 | } |
2602 | assert(obat->cnt == BATcount(quick_descriptor(obat->bid))); |
2603 | obat->cleared = 0; |
2604 | bat_destroy(cur); |
2605 | if (obat->next) { |
2606 | ok = destroy_bat(obat->next); |
2607 | obat->next = NULL; |
2608 | } |
2609 | return ok; |
2610 | } |
2611 | |
2612 | static int |
2613 | tr_update_dbat(sql_trans *tr, sql_dbat *tdb, sql_dbat *fdb) |
2614 | { |
2615 | int ok = LOG_OK; |
2616 | BAT *db = NULL; |
2617 | |
2618 | if (fdb->cached) { |
2619 | bat_destroy(fdb->cached); |
2620 | fdb->cached = NULL; |
2621 | } |
2622 | if (tdb->cached) { |
2623 | bat_destroy(tdb->cached); |
2624 | tdb->cached = NULL; |
2625 | } |
2626 | assert(ATOMIC_GET(&store_nr_active)==1); |
2627 | db = temp_descriptor(fdb->dbid); |
2628 | if(!db) |
2629 | return LOG_ERR; |
2630 | if (tdb->cnt < BATcount(db) || fdb->cleared) { |
2631 | BAT *odb = temp_descriptor(tdb->dbid); |
2632 | if(odb) { |
2633 | if (isEbat(odb)){ |
2634 | temp_destroy(tdb->dbid); |
2635 | tdb->dbid = temp_copy(odb->batCacheid, false); |
2636 | bat_destroy(odb); |
2637 | if (tdb->dbid == BID_NIL || (odb = temp_descriptor(tdb->dbid)) == NULL) |
2638 | return LOG_ERR; |
2639 | } |
2640 | if (fdb->cleared) { |
2641 | tdb->cleared = 1; |
2642 | tdb->cnt = 0; |
2643 | bat_clear(odb); |
2644 | } |
2645 | db->batInserted = tdb->cnt; |
2646 | if (append_inserted(odb, db) == BUN_NONE) |
2647 | ok = LOG_ERR; |
2648 | else |
2649 | BATcommit(odb); |
2650 | assert(BATcount(odb) == fdb->cnt); |
2651 | temp_destroy(fdb->dbid); |
2652 | |
2653 | if (ok == LOG_OK) { |
2654 | fdb->dbid = 0; |
2655 | assert(BATcount(db) == fdb->cnt); |
2656 | tdb->cnt = fdb->cnt; |
2657 | } |
2658 | bat_destroy(odb); |
2659 | } else { |
2660 | ok = LOG_ERR; |
2661 | } |
2662 | } |
2663 | bat_destroy(db); |
2664 | if (ok == LOG_OK && tdb->next) { |
2665 | ok = destroy_dbat(tr, tdb->next); |
2666 | tdb->next = NULL; |
2667 | } |
2668 | return ok; |
2669 | } |
2670 | |
2671 | static int |
2672 | tr_merge_dbat(sql_trans *tr, sql_dbat *tdb) |
2673 | { |
2674 | int ok = LOG_OK; |
2675 | |
2676 | if (tdb->cached) { |
2677 | bat_destroy(tdb->cached); |
2678 | tdb->cached = NULL; |
2679 | } |
2680 | assert(ATOMIC_GET(&store_nr_active)==1); |
2681 | if (tdb->next) { |
2682 | ok = destroy_dbat(tr, tdb->next); |
2683 | tdb->next = NULL; |
2684 | } |
2685 | return ok; |
2686 | } |
2687 | |
2688 | static int |
2689 | update_table(sql_trans *tr, sql_table *ft, sql_table *tt) |
2690 | { |
2691 | sql_trans *oldest = oldest_active_transaction(); |
2692 | sql_table *ot = NULL; |
2693 | int ok = LOG_OK; |
2694 | node *n, *m, *o = NULL; |
2695 | |
2696 | if (ATOMIC_GET(&store_nr_active) == 1 || ft->base.allocated) { |
2697 | if (ATOMIC_GET(&store_nr_active) > 1 && ft->data) { /* move delta */ |
2698 | sql_dbat *b = ft->data; |
2699 | |
2700 | if (!tt->data) |
2701 | tt->base.allocated = ft->base.allocated; |
2702 | ft->data = NULL; |
2703 | b->next = tt->data; |
2704 | tt->data = b; |
2705 | |
2706 | if (b->cached) { |
2707 | bat_destroy(b->cached); |
2708 | b->cached = NULL; |
2709 | } |
2710 | while (b && b->wtime >= oldest->stime) |
2711 | b = b->next; |
2712 | /* find table t->base.stime */ |
2713 | ot = tr_find_table(oldest, tt); |
2714 | if (b && ot && b->wtime < ot->base.stime) { |
2715 | /* anything older can go */ |
2716 | delayed_destroy_dbat(b->next); |
2717 | b->next = NULL; |
2718 | } |
2719 | } else if (tt->data && ft->base.allocated) { |
2720 | if (tr_update_dbat(tr, tt->data, ft->data) != LOG_OK) |
2721 | ok = LOG_ERR; |
2722 | } else if (ATOMIC_GET(&store_nr_active) == 1 && !ft->base.allocated) { |
2723 | /* only insert/updates, merge earlier deletes */ |
2724 | if (!tt->data) { |
2725 | sql_table *ot = tr_find_table(tr->parent, tt); |
2726 | tt->data = timestamp_dbat(ot->data, tt->base.stime); |
2727 | } |
2728 | assert(tt->data); |
2729 | if (tr_merge_dbat(tr, tt->data) != LOG_OK) |
2730 | ok = LOG_ERR; |
2731 | ft->data = NULL; |
2732 | } else if (ft->data) { |
2733 | tt->data = ft->data; |
2734 | tt->base.allocated = 1; |
2735 | ft->data = NULL; |
2736 | } |
2737 | } |
2738 | if (ot) |
2739 | o = ot->columns.set->h; |
2740 | for (n = ft->columns.set->h, m = tt->columns.set->h; ok == LOG_OK && n && m; n = n->next, m = m->next, o=(o?o->next:NULL)) { |
2741 | sql_column *cc = n->data; // TODO: either stick to to/from terminology or old/current terminology |
2742 | sql_column *oc = m->data; |
2743 | |
2744 | if (ATOMIC_GET(&store_nr_active) == 1 || (cc->base.wtime && cc->base.allocated)) { |
2745 | assert(!cc->base.wtime || oc->base.wtime < cc->base.wtime); |
2746 | if (ATOMIC_GET(&store_nr_active) > 1 && cc->data) { /* move delta */ |
2747 | sql_delta *b = cc->data; |
2748 | sql_column *oldc = NULL; |
2749 | |
2750 | if (!oc->data) |
2751 | oc->base.allocated = cc->base.allocated; |
2752 | cc->data = NULL; |
2753 | b->next = oc->data; |
2754 | oc->data = b; |
2755 | |
2756 | if (b->cached) { |
2757 | bat_destroy(b->cached); |
2758 | b->cached = NULL; |
2759 | } |
2760 | while (b && b->wtime >= oldest->stime) |
2761 | b = b->next; |
2762 | /* find column c->base.stime */ |
2763 | if (o) |
2764 | oldc = o->data; |
2765 | if (oldc && b && oldc->base.id == cc->base.id && b->wtime < oldc->base.stime) { |
2766 | /* anything older can go */ |
2767 | delayed_destroy_bat(b->next); |
2768 | b->next = NULL; |
2769 | } |
2770 | } else if (oc->data && cc->base.allocated) { |
2771 | if (tr_update_delta(tr, oc->data, cc->data, cc->unique == 1) != LOG_OK) |
2772 | ok = LOG_ERR; |
2773 | } else if (ATOMIC_GET(&store_nr_active) == 1 && !cc->base.allocated) { |
2774 | /* only deletes, merge earlier changes */ |
2775 | if (!oc->data) { |
2776 | sql_column *o = tr_find_column(tr->parent, oc); |
2777 | oc->data = timestamp_delta(o->data, oc->base.stime); |
2778 | } |
2779 | assert(oc->data); |
2780 | if (tr_merge_delta(tr, oc->data, oc->unique == 1) != LOG_OK) |
2781 | ok = LOG_ERR; |
2782 | cc->data = NULL; |
2783 | } else if (cc->data) { |
2784 | oc->data = cc->data; |
2785 | oc->base.allocated = 1; |
2786 | cc->data = NULL; |
2787 | } |
2788 | } |
2789 | |
2790 | oc->colnr = cc->colnr; |
2791 | oc->null = cc->null; |
2792 | oc->unique = cc->unique; |
2793 | if (cc->storage_type && (!oc->storage_type || strcmp(cc->storage_type, oc->storage_type) != 0)) |
2794 | oc->storage_type = sa_strdup(tr->parent->sa, cc->storage_type); |
2795 | if (!cc->storage_type) |
2796 | oc->storage_type = NULL; |
2797 | if (cc->def && (!oc->def || strcmp(cc->def, oc->def) != 0)) |
2798 | oc->def = sa_strdup(tr->parent->sa, cc->def); |
2799 | if (!cc->def) |
2800 | oc->def = NULL; |
2801 | |
2802 | if (isRenamed(cc)) { /* apply possible renaming */ |
2803 | list_hash_delete(oc->t->columns.set, oc, NULL); |
2804 | oc->base.name = sa_strdup(tr->parent->sa, cc->base.name); |
2805 | if (!list_hash_add(oc->t->columns.set, oc, NULL)) |
2806 | ok = LOG_ERR; |
2807 | setRenamedFlag(oc); /* propagate the change to the upper transaction */ |
2808 | } |
2809 | |
2810 | if (oc->base.rtime < cc->base.rtime) |
2811 | oc->base.rtime = cc->base.rtime; |
2812 | if (oc->base.wtime < cc->base.wtime) |
2813 | oc->base.wtime = cc->base.wtime; |
2814 | if (cc->data) |
2815 | destroy_col(tr, cc); |
2816 | cc->base.allocated = 0; |
2817 | } |
2818 | if (ok == LOG_OK && tt->idxs.set) { |
2819 | o = NULL; |
2820 | if (ot) |
2821 | o = ot->idxs.set->h; |
2822 | for (n = ft->idxs.set->h, m = tt->idxs.set->h; ok == LOG_OK && n && m; n = n->next, m = m->next, o=(o?o->next:NULL)) { |
2823 | sql_idx *ci = n->data; |
2824 | sql_idx *oi = m->data; |
2825 | |
2826 | /* some indices have no bats */ |
2827 | if (!oi->data) { |
2828 | ci->data = NULL; |
2829 | ci->base.allocated = 0; |
2830 | continue; |
2831 | } |
2832 | if (ATOMIC_GET(&store_nr_active) == 1 || (ci->base.wtime && ci->base.allocated)) { |
2833 | if (ATOMIC_GET(&store_nr_active) > 1 && ci->data) { /* move delta */ |
2834 | sql_delta *b = ci->data; |
2835 | sql_idx *oldi = NULL; |
2836 | |
2837 | if (!oi->data) |
2838 | oi->base.allocated = ci->base.allocated; |
2839 | ci->data = NULL; |
2840 | b->next = oi->data; |
2841 | oi->data = b; |
2842 | if (b->cached) { |
2843 | bat_destroy(b->cached); |
2844 | b->cached = NULL; |
2845 | } |
2846 | while (b && b->wtime >= oldest->stime) |
2847 | b = b->next; |
2848 | /* find idx i->base.stime */ |
2849 | if (o) |
2850 | oldi = o->data; |
2851 | if (oldi && b && oldi->base.id == ci->base.id && b->wtime < oldi->base.stime) { |
2852 | /* anything older can go */ |
2853 | delayed_destroy_bat(b->next); |
2854 | b->next = NULL; |
2855 | } |
2856 | } else if (oi->data && ci->base.allocated) { |
2857 | if (tr_update_delta(tr, oi->data, ci->data, 0) != LOG_OK) |
2858 | ok = LOG_ERR; |
2859 | } else if (ATOMIC_GET(&store_nr_active) == 1 && !ci->base.allocated) { |
2860 | if (!oi->data) { |
2861 | sql_idx *o = tr_find_idx(tr->parent, oi); |
2862 | oi->data = timestamp_delta(o->data, oi->base.stime); |
2863 | } |
2864 | assert(oi->data); |
2865 | if (tr_merge_delta(tr, oi->data, 0) != LOG_OK) |
2866 | ok = LOG_ERR; |
2867 | ci->data = NULL; |
2868 | } else if (ci->data) { |
2869 | oi->data = ci->data; |
2870 | oi->base.allocated = 1; |
2871 | ci->data = NULL; |
2872 | } |
2873 | } |
2874 | |
2875 | if (oi->base.rtime < ci->base.rtime) |
2876 | oi->base.rtime = ci->base.rtime; |
2877 | if (oi->base.wtime < ci->base.wtime) |
2878 | oi->base.wtime = ci->base.wtime; |
2879 | if (ci->data) |
2880 | destroy_idx(tr, ci); |
2881 | ci->base.allocated = 0; |
2882 | } |
2883 | } |
2884 | if (tt->base.rtime < ft->base.rtime) |
2885 | tt->base.rtime = ft->base.rtime; |
2886 | if (tt->base.wtime < ft->base.wtime) |
2887 | tt->base.wtime = ft->base.wtime; |
2888 | if (ft->data) |
2889 | destroy_del(tr, ft); |
2890 | ft->base.allocated = 0; |
2891 | return ok; |
2892 | } |
2893 | |
2894 | static int |
2895 | tr_log_delta( sql_trans *tr, sql_delta *cbat, int cleared, char tpe, oid id) |
2896 | { |
2897 | gdk_return ok = GDK_SUCCEED; |
2898 | BAT *ins; |
2899 | |
2900 | (void)tr; |
2901 | if (GDKinmemory()) |
2902 | return LOG_OK; |
2903 | |
2904 | assert(tr->parent == gtrans); |
2905 | ins = temp_descriptor(cbat->ibid); |
2906 | if (ins == NULL) |
2907 | return LOG_ERR; |
2908 | |
2909 | if (cleared && log_bat_clear(bat_logger, cbat->name, tpe, id) != GDK_SUCCEED) { |
2910 | bat_destroy(ins); |
2911 | return LOG_ERR; |
2912 | } |
2913 | |
2914 | /* any inserts */ |
2915 | if (BUNlast(ins) > 0) { |
2916 | assert(ATOMIC_GET(&store_nr_active)>0); |
2917 | if (BUNlast(ins) > ins->batInserted && |
2918 | (ATOMIC_GET(&store_nr_active) != 1 || |
2919 | cbat->ibase || |
2920 | BATcount(ins) <= SNAPSHOT_MINSIZE)) |
2921 | ok = log_bat(bat_logger, ins, cbat->name, tpe, id); |
2922 | if (ok == GDK_SUCCEED && ATOMIC_GET(&store_nr_active) == 1 && |
2923 | !cbat->ibase && BATcount(ins) > SNAPSHOT_MINSIZE) { |
2924 | /* log new snapshot */ |
2925 | if ((ok = logger_add_bat(bat_logger, ins, cbat->name, tpe, id)) == GDK_SUCCEED) |
2926 | ok = log_bat_persists(bat_logger, ins, cbat->name, tpe, id); |
2927 | } |
2928 | } |
2929 | bat_destroy(ins); |
2930 | |
2931 | if (ok == GDK_SUCCEED && cbat->ucnt && cbat->uibid) { |
2932 | BAT *ui = temp_descriptor(cbat->uibid); |
2933 | BAT *uv = temp_descriptor(cbat->uvbid); |
2934 | /* any updates */ |
2935 | if (ui == NULL || uv == NULL) { |
2936 | ok = GDK_FAIL; |
2937 | } else if (BUNlast(uv) > uv->batInserted || BATdirty(uv)) |
2938 | ok = log_delta(bat_logger, ui, uv, cbat->name, tpe, id); |
2939 | bat_destroy(ui); |
2940 | bat_destroy(uv); |
2941 | } |
2942 | return ok == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
2943 | } |
2944 | |
2945 | static int |
2946 | tr_log_dbat(sql_trans *tr, sql_dbat *fdb, int cleared, char tpe, oid id) |
2947 | { |
2948 | gdk_return ok = GDK_SUCCEED; |
2949 | BAT *db = NULL; |
2950 | |
2951 | if (!fdb || GDKinmemory()) |
2952 | return LOG_OK; |
2953 | |
2954 | (void)tr; |
2955 | assert (fdb->dname); |
2956 | if (cleared && log_bat_clear(bat_logger, fdb->dname, tpe, id) != GDK_SUCCEED) |
2957 | return LOG_ERR; |
2958 | |
2959 | db = temp_descriptor(fdb->dbid); |
2960 | if(!db) |
2961 | return LOG_ERR; |
2962 | if (BUNlast(db) > 0) { |
2963 | assert(ATOMIC_GET(&store_nr_active)>0); |
2964 | if (BUNlast(db) > db->batInserted) |
2965 | ok = log_bat(bat_logger, db, fdb->dname, tpe, id); |
2966 | } |
2967 | bat_destroy(db); |
2968 | return ok == GDK_SUCCEED ? LOG_OK : LOG_ERR; |
2969 | } |
2970 | |
2971 | static int |
2972 | log_table(sql_trans *tr, sql_table *ft) |
2973 | { |
2974 | int ok = LOG_OK; |
2975 | node *n; |
2976 | |
2977 | assert(tr->parent == gtrans); |
2978 | if (ft->base.wtime && ft->base.allocated) |
2979 | ok = tr_log_dbat(tr, ft->data, ft->cleared, ft->bootstrap?0:LOG_TAB, ft->base.id); |
2980 | for (n = ft->columns.set->h; ok == LOG_OK && n; n = n->next) { |
2981 | sql_column *cc = n->data; |
2982 | |
2983 | if (!cc->base.wtime || !cc->base.allocated) |
2984 | continue; |
2985 | ok = tr_log_delta(tr, cc->data, ft->cleared, ft->bootstrap?0:LOG_COL, cc->base.id); |
2986 | } |
2987 | if (ok == LOG_OK && ft->idxs.set) { |
2988 | for (n = ft->idxs.set->h; ok == LOG_OK && n; n = n->next) { |
2989 | sql_idx *ci = n->data; |
2990 | |
2991 | /* some indices have no bats or changes */ |
2992 | if (!ci->data || !ci->base.wtime || !ci->base.allocated) |
2993 | continue; |
2994 | |
2995 | ok = tr_log_delta(tr, ci->data, ft->cleared, ft->bootstrap?0:LOG_IDX, ci->base.id); |
2996 | } |
2997 | } |
2998 | return ok; |
2999 | } |
3000 | |
3001 | static int |
3002 | snapshot_bat(sql_delta *cbat) |
3003 | { |
3004 | if (!cbat->ibase && cbat->cnt > SNAPSHOT_MINSIZE) { |
3005 | BAT *ins = temp_descriptor(cbat->ibid); |
3006 | if(ins) { |
3007 | if (BATsave(ins) != GDK_SUCCEED) { |
3008 | bat_destroy(ins); |
3009 | return LOG_ERR; |
3010 | } |
3011 | bat_destroy(ins); |
3012 | } |
3013 | } |
3014 | return LOG_OK; |
3015 | } |
3016 | |
3017 | static int |
3018 | save_snapshot(sql_table *ft) |
3019 | { |
3020 | int ok = LOG_OK; |
3021 | node *n; |
3022 | |
3023 | for (n = ft->columns.set->h; ok == LOG_OK && n; n = n->next) { |
3024 | sql_column *cc = n->data; |
3025 | |
3026 | if (!cc->base.wtime || !cc->base.allocated) |
3027 | continue; |
3028 | if (snapshot_bat(cc->data) != LOG_OK) |
3029 | return LOG_ERR; |
3030 | } |
3031 | if (ok == LOG_OK && ft->idxs.set) { |
3032 | for (n = ft->idxs.set->h; ok == LOG_OK && n; n = n->next) { |
3033 | sql_idx *ci = n->data; |
3034 | |
3035 | /* some indices have no bats or changes */ |
3036 | if (!ci->data || !ci->base.wtime || !ci->base.allocated) |
3037 | continue; |
3038 | |
3039 | if (snapshot_bat(ci->data) != LOG_OK) |
3040 | return LOG_ERR; |
3041 | } |
3042 | } |
3043 | return LOG_OK; |
3044 | } |
3045 | |
3046 | static int |
3047 | tr_snapshot_bat( sql_trans *tr, sql_delta *cbat) |
3048 | { |
3049 | int ok = LOG_OK; |
3050 | |
3051 | assert(tr->parent == gtrans); |
3052 | assert(ATOMIC_GET(&store_nr_active)>0); |
3053 | |
3054 | (void)tr; |
3055 | if (ATOMIC_GET(&store_nr_active) == 1 && !cbat->ibase && cbat->cnt > SNAPSHOT_MINSIZE) { |
3056 | BAT *ins = temp_descriptor(cbat->ibid); |
3057 | if(ins) { |
3058 | /* any inserts */ |
3059 | if (BUNlast(ins) > 0) { |
3060 | bat_set_access(ins, BAT_READ); |
3061 | BATmode(ins, false); |
3062 | } |
3063 | bat_destroy(ins); |
3064 | } else { |
3065 | ok = LOG_ERR; |
3066 | } |
3067 | } |
3068 | return ok; |
3069 | } |
3070 | |
3071 | static int |
3072 | snapshot_table(sql_trans *tr, sql_table *ft) |
3073 | { |
3074 | int ok = LOG_OK; |
3075 | node *n; |
3076 | |
3077 | assert(tr->parent == gtrans); |
3078 | |
3079 | for (n = ft->columns.set->h; ok == LOG_OK && n; n = n->next) { |
3080 | sql_column *cc = n->data; |
3081 | |
3082 | if (!cc->base.wtime || !cc->base.allocated) |
3083 | continue; |
3084 | tr_snapshot_bat(tr, cc->data); |
3085 | } |
3086 | if (ok == LOG_OK && ft->idxs.set) { |
3087 | for (n = ft->idxs.set->h; ok == LOG_OK && n; n = n->next) { |
3088 | sql_idx *ci = n->data; |
3089 | |
3090 | /* some indices have no bats or changes */ |
3091 | if (!ci->data || !ci->base.wtime || !ci->base.allocated) |
3092 | continue; |
3093 | |
3094 | tr_snapshot_bat(tr, ci->data); |
3095 | } |
3096 | } |
3097 | return ok; |
3098 | } |
3099 | |
3100 | void |
3101 | bat_storage_init( store_functions *sf) |
3102 | { |
3103 | sf->bind_col = (bind_col_fptr)&bind_col; |
3104 | sf->bind_idx = (bind_idx_fptr)&bind_idx; |
3105 | sf->bind_del = (bind_del_fptr)&bind_del; |
3106 | |
3107 | sf->append_col = (append_col_fptr)&append_col; |
3108 | sf->append_idx = (append_idx_fptr)&append_idx; |
3109 | sf->update_col = (update_col_fptr)&update_col; |
3110 | sf->update_idx = (update_idx_fptr)&update_idx; |
3111 | sf->delete_tab = (delete_tab_fptr)&delete_tab; |
3112 | |
3113 | sf->count_del = (count_del_fptr)&count_del; |
3114 | sf->count_upd = (count_upd_fptr)&count_upd; |
3115 | sf->count_col = (count_col_fptr)&count_col; |
3116 | sf->count_col_upd = (count_col_upd_fptr)&count_col_upd; |
3117 | sf->count_idx = (count_idx_fptr)&count_idx; |
3118 | sf->dcount_col = (dcount_col_fptr)&dcount_col; |
3119 | sf->sorted_col = (prop_col_fptr)&sorted_col; |
3120 | sf->double_elim_col = (prop_col_fptr)&double_elim_col; |
3121 | |
3122 | sf->create_col = (create_col_fptr)&create_col; |
3123 | sf->create_idx = (create_idx_fptr)&create_idx; |
3124 | sf->create_del = (create_del_fptr)&create_del; |
3125 | |
3126 | sf->upgrade_col = (upgrade_col_fptr)&upgrade_col; |
3127 | sf->upgrade_idx = (upgrade_idx_fptr)&upgrade_idx; |
3128 | sf->upgrade_del = (upgrade_del_fptr)&upgrade_del; |
3129 | |
3130 | sf->log_create_col = (create_col_fptr)&log_create_col; |
3131 | sf->log_create_idx = (create_idx_fptr)&log_create_idx; |
3132 | sf->log_create_del = (create_del_fptr)&log_create_del; |
3133 | |
3134 | sf->snapshot_create_col = (create_col_fptr)&snapshot_create_col; |
3135 | sf->snapshot_create_idx = (create_idx_fptr)&snapshot_create_idx; |
3136 | sf->snapshot_create_del = (create_del_fptr)&snapshot_create_del; |
3137 | |
3138 | sf->save_snapshot = (snapshot_fptr)&save_snapshot; |
3139 | |
3140 | sf->dup_col = (dup_col_fptr)&dup_col; |
3141 | sf->dup_idx = (dup_idx_fptr)&dup_idx; |
3142 | sf->dup_del = (dup_del_fptr)&dup_del; |
3143 | |
3144 | sf->destroy_col = (destroy_col_fptr)&destroy_col; |
3145 | sf->destroy_idx = (destroy_idx_fptr)&destroy_idx; |
3146 | sf->destroy_del = (destroy_del_fptr)&destroy_del; |
3147 | |
3148 | sf->log_destroy_col = (destroy_col_fptr)&log_destroy_col; |
3149 | sf->log_destroy_idx = (destroy_idx_fptr)&log_destroy_idx; |
3150 | sf->log_destroy_del = (destroy_del_fptr)&log_destroy_del; |
3151 | |
3152 | sf->clear_col = (clear_col_fptr)&clear_col; |
3153 | sf->clear_idx = (clear_idx_fptr)&clear_idx; |
3154 | sf->clear_del = (clear_del_fptr)&clear_del; |
3155 | |
3156 | sf->update_table = (update_table_fptr)&update_table; |
3157 | sf->log_table = (update_table_fptr)&log_table; |
3158 | sf->snapshot_table = (update_table_fptr)&snapshot_table; |
3159 | sf->gtrans_update = (gtrans_update_fptr)>r_update; |
3160 | sf->gtrans_minmax = (gtrans_update_fptr)>r_minmax; |
3161 | |
3162 | sf->cleanup = (cleanup_fptr)&cleanup; |
3163 | } |
3164 | |