LCOV - code coverage report
Current view: top level - sql/storage/bat - bat_logger.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 345 880 39.2 %
Date: 2024-12-20 21:24:02 Functions: 23 23 100.0 %

          Line data    Source code
       1             : /*
       2             :  * SPDX-License-Identifier: MPL-2.0
       3             :  *
       4             :  * This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       7             :  *
       8             :  * Copyright 2024 MonetDB Foundation;
       9             :  * Copyright August 2008 - 2023 MonetDB B.V.;
      10             :  * Copyright 1997 - July 2008 CWI.
      11             :  */
      12             : 
      13             : #include "monetdb_config.h"
      14             : #include "bat_logger.h"
      15             : #include "bat_utils.h"
      16             : #include "sql_types.h" /* EC_POS */
      17             : #include "gdk_logger_internals.h"
      18             : #include "mutils.h"
      19             : 
      20             : #define CATALOG_JUL2021 52300   /* first in Jul2021 */
      21             : #define CATALOG_JAN2022 52301   /* first in Jan2022 */
      22             : #define CATALOG_SEP2022 52302   /* first in Sep2022 */
      23             : #define CATALOG_AUG2024 52303   /* first in Aug2024 */
      24             : 
      25             : /* Note, CATALOG version 52300 is the first one where the basic system
      26             :  * tables (the ones created in store.c) have fixed and unchangeable
      27             :  * ids. */
      28             : 
      29             : /* return GDK_SUCCEED if we can handle the upgrade from oldversion to
      30             :  * newversion */
      31             : static gdk_return
      32          16 : bl_preversion(sqlstore *store, int oldversion, int newversion)
      33             : {
      34          16 :         (void)newversion;
      35             : 
      36             : #ifdef CATALOG_JUL2021
      37          16 :         if (oldversion == CATALOG_JUL2021) {
      38             :                 /* upgrade to default releases */
      39           0 :                 store->catalog_version = oldversion;
      40           0 :                 return GDK_SUCCEED;
      41             :         }
      42             : #endif
      43             : 
      44             : #ifdef CATALOG_JAN2022
      45          16 :         if (oldversion == CATALOG_JAN2022) {
      46             :                 /* upgrade to default releases */
      47           0 :                 store->catalog_version = oldversion;
      48           0 :                 return GDK_SUCCEED;
      49             :         }
      50             : #endif
      51             : 
      52             : #ifdef CATALOG_SEP2022
      53          16 :         if (oldversion == CATALOG_SEP2022) {
      54             :                 /* upgrade to default releases */
      55           8 :                 store->catalog_version = oldversion;
      56           8 :                 return GDK_SUCCEED;
      57             :         }
      58             : #endif
      59             : 
      60             : #ifdef CATALOG_AUG2024
      61           8 :         if (oldversion == CATALOG_AUG2024) {
      62             :                 /* upgrade to default releases */
      63           8 :                 store->catalog_version = oldversion;
      64           8 :                 return GDK_SUCCEED;
      65             :         }
      66             : #endif
      67             : 
      68             :         return GDK_FAIL;
      69             : }
      70             : 
      71             : #if defined CATALOG_JUL2021 || defined CATALOG_JAN2022
      72             : /* replace a column in a system table with a new column
      73             :  * colid is the SQL id for the column, newcol is the new BAT */
      74             : static gdk_return
      75          32 : replace_bat(logger *lg, int colid, BAT *newcol)
      76             : {
      77          32 :         gdk_return rc;
      78          32 :         newcol = BATsetaccess(newcol, BAT_READ);
      79          32 :         if (newcol == NULL)
      80             :                 return GDK_FAIL;
      81          32 :         if ((rc = BAThash(lg->catalog_id)) == GDK_SUCCEED) {
      82          32 :                 BATiter cii = bat_iterator_nolock(lg->catalog_id);
      83          32 :                 BUN p;
      84          32 :                 MT_rwlock_rdlock(&cii.b->thashlock);
      85          86 :                 HASHloop_int(cii, cii.b->thash, p, &colid) {
      86          32 :                         if (BUNfnd(lg->dcatalog, &(oid){(oid)p}) == BUN_NONE) {
      87          64 :                                 if (BUNappend(lg->dcatalog, &(oid){(oid)p}, true) != GDK_SUCCEED ||
      88          32 :                                         BUNreplace(lg->catalog_lid, (oid) p, &(lng){0}, false) != GDK_SUCCEED) {
      89           0 :                                         MT_rwlock_rdunlock(&cii.b->thashlock);
      90           0 :                                         return GDK_FAIL;
      91             :                                 }
      92          32 :                                 break;
      93             :                         }
      94             :                 }
      95          32 :                 MT_rwlock_rdunlock(&cii.b->thashlock);
      96          32 :                 if ((rc = BUNappend(lg->catalog_id, &colid, true)) == GDK_SUCCEED &&
      97          32 :                         (rc = BUNappend(lg->catalog_bid, &newcol->batCacheid, true)) == GDK_SUCCEED &&
      98          32 :                         (rc = BUNappend(lg->catalog_lid, &lng_nil, false)) == GDK_SUCCEED &&
      99          32 :                         (rc = BUNappend(lg->catalog_cnt, &(lng){BATcount(newcol)}, false)) == GDK_SUCCEED) {
     100          32 :                         BBPretain(newcol->batCacheid);
     101             :                 }
     102             :         }
     103             :         return rc;
     104             : }
     105             : #endif
     106             : 
     107             : static BAT *
     108         488 : log_temp_descriptor(log_bid b)
     109             : {
     110         488 :         if (b <= 0)
     111             :                 return NULL;
     112         488 :         return temp_descriptor(b);
     113             : }
     114             : 
     115             : #if defined CATALOG_JAN2022 || defined CATALOG_SEP2022 || defined CATALOG_AUG2024
     116             : /* cannot use attribute((sentinel)) since sentinel is not a pointer */
     117             : static gdk_return
     118          32 : tabins(logger *lg, ...)
     119             : {
     120          32 :         va_list va;
     121          32 :         int cid;
     122          32 :         const void *cval;
     123          32 :         gdk_return rc;
     124          32 :         BAT *b;
     125             : 
     126          32 :         va_start(va, lg);
     127          32 :         BATiter cni = bat_iterator(lg->catalog_id);
     128         384 :         while ((cid = va_arg(va, int)) != 0) {
     129         352 :                 cval = va_arg(va, void *);
     130         704 :                 if ((b = log_temp_descriptor(log_find_bat(lg, cid))) == NULL) {
     131             :                         rc = GDK_FAIL;
     132             :                         break;
     133             :                 }
     134         352 :                 rc = BUNappend(b, cval, true);
     135         352 :                 if (rc == GDK_SUCCEED) {
     136         352 :                         BUN p;
     137         352 :                         MT_rwlock_rdlock(&cni.b->thashlock);
     138         409 :                         HASHloop_int(cni, cni.b->thash, p, &cid) {
     139         352 :                                 if (BUNfnd(lg->dcatalog, &(oid){p}) == BUN_NONE) {
     140         352 :                                         rc = BUNreplace(lg->catalog_cnt, p, &(lng){BATcount(b)}, false);
     141         352 :                                         break;
     142             :                                 }
     143             :                         }
     144         352 :                         MT_rwlock_rdunlock(&cni.b->thashlock);
     145             :                 }
     146         352 :                 bat_destroy(b);
     147         352 :                 if (rc != GDK_SUCCEED)
     148             :                         break;
     149             :         }
     150          32 :         bat_iterator_end(&cni);
     151          32 :         va_end(va);
     152          32 :         return rc;
     153             : }
     154             : #endif
     155             : 
     156             : static gdk_return
     157          16 : bl_postversion(void *Store, logger *lg)
     158             : {
     159          16 :         sqlstore *store = Store;
     160          16 :         gdk_return rc;
     161             : 
     162             : #ifdef CATALOG_JUL2021
     163          16 :         if (store->catalog_version <= CATALOG_JUL2021) {
     164             :                 /* change the language attribute in sys.functions for sys.env,
     165             :                  * sys.var, and sys.db_users from SQL to MAL */
     166             : 
     167             :                 /* sys.functions i.e. deleted rows */
     168           0 :                 BAT *del_funcs = log_temp_descriptor(log_find_bat(lg, 2016));
     169           0 :                 if (del_funcs == NULL)
     170           0 :                         return GDK_FAIL;
     171           0 :                 BAT *func_tid = BATmaskedcands(0, BATcount(del_funcs), del_funcs, false);
     172           0 :                 bat_destroy(del_funcs);
     173             :                 /* sys.functions.schema_id */
     174           0 :                 BAT *func_schem = log_temp_descriptor(log_find_bat(lg, 2026));
     175           0 :                 if (func_tid == NULL || func_schem == NULL) {
     176           0 :                         bat_destroy(func_tid);
     177           0 :                         bat_destroy(func_schem);
     178           0 :                         return GDK_FAIL;
     179             :                 }
     180             :                 /* select * from sys.functions where schema_id = 2000 */
     181           0 :                 BAT *cands = BATselect(func_schem, func_tid, &(int) {2000}, NULL, true, true, false, false);
     182           0 :                 bat_destroy(func_schem);
     183           0 :                 if (cands == NULL) {
     184           0 :                         bat_destroy(func_tid);
     185           0 :                         return GDK_FAIL;
     186             :                 }
     187             :                 /* the functions we need to change */
     188           0 :                 BAT *funcs = COLnew(0, TYPE_str, 3, TRANSIENT);
     189           0 :                 if (funcs == NULL ||
     190           0 :                         BUNappend(funcs, "db_users", false) != GDK_SUCCEED ||
     191           0 :                         BUNappend(funcs, "env", false) != GDK_SUCCEED ||
     192           0 :                         BUNappend(funcs, "var", false) != GDK_SUCCEED) {
     193           0 :                         bat_destroy(cands);
     194           0 :                         bat_destroy(funcs);
     195           0 :                         bat_destroy(func_tid);
     196           0 :                         return GDK_FAIL;
     197             :                 }
     198             :                 /* sys.functions.name */
     199           0 :                 BAT *func_name = log_temp_descriptor(log_find_bat(lg, 2018));
     200           0 :                 if (func_name == NULL) {
     201           0 :                         bat_destroy(cands);
     202           0 :                         bat_destroy(funcs);
     203           0 :                         bat_destroy(func_tid);
     204           0 :                         return GDK_FAIL;
     205             :                 }
     206             :                 /* select * from sys.functions where schema_id = 2000 and name in (...) */
     207           0 :                 BAT *b = BATintersect(func_name, funcs, cands, NULL, false, false, 3);
     208           0 :                 bat_destroy(cands);
     209           0 :                 bat_destroy(func_name);
     210           0 :                 bat_destroy(funcs);
     211           0 :                 cands = b;
     212           0 :                 if (cands == NULL) {
     213           0 :                         bat_destroy(func_tid);
     214           0 :                         return GDK_FAIL;
     215             :                 }
     216             :                 /* sys.functions.language */
     217           0 :                 BAT *func_lang = log_temp_descriptor(log_find_bat(lg, 2021));
     218           0 :                 if (func_lang == NULL) {
     219           0 :                         bat_destroy(cands);
     220           0 :                         bat_destroy(func_tid);
     221           0 :                         return GDK_FAIL;
     222             :                 }
     223             :                 /* select * from sys.functions where schema_id = 2000 and name in (...)
     224             :                  * and language = FUNC_LANG_SQL */
     225           0 :                 b = BATselect(func_lang, cands, &(int) {FUNC_LANG_SQL}, NULL, true, true, false, false);
     226           0 :                 bat_destroy(cands);
     227           0 :                 cands = b;
     228           0 :                 if (cands == NULL) {
     229           0 :                         bat_destroy(func_lang);
     230           0 :                         bat_destroy(func_tid);
     231           0 :                         return GDK_FAIL;
     232             :                 }
     233           0 :                 b = BATconstant(0, TYPE_int, &(int) {FUNC_LANG_MAL}, BATcount(cands), TRANSIENT);
     234           0 :                 if (b == NULL) {
     235           0 :                         bat_destroy(func_lang);
     236           0 :                         bat_destroy(cands);
     237           0 :                         bat_destroy(func_tid);
     238           0 :                         return GDK_FAIL;
     239             :                 }
     240           0 :                 rc = GDK_FAIL;
     241           0 :                 BAT *b2 = COLcopy(func_lang, func_lang->ttype, true, PERSISTENT);
     242           0 :                 if (b2 == NULL ||
     243           0 :                         BATreplace(b2, cands, b, false) != GDK_SUCCEED) {
     244           0 :                         bat_destroy(b2);
     245           0 :                         bat_destroy(cands);
     246           0 :                         bat_destroy(b);
     247           0 :                         bat_destroy(func_tid);
     248           0 :                         bat_destroy(func_lang);
     249           0 :                         return GDK_FAIL;
     250             :                 }
     251           0 :                 bat_destroy(b);
     252           0 :                 bat_destroy(cands);
     253             : 
     254             :                 /* additionally, update the language attribute for entries
     255             :                  * that were declared using "EXTERNAL NAME" to be MAL functions
     256             :                  * instead of SQL functions (a problem that seems to have
     257             :                  * occurred in ancient databases) */
     258             : 
     259             :                 /* sys.functions.func */
     260           0 :                 BAT *func_func = log_temp_descriptor(log_find_bat(lg, 2019));
     261           0 :                 if (func_func == NULL) {
     262           0 :                         bat_destroy(func_tid);
     263           0 :                         bat_destroy(b2);
     264           0 :                         return GDK_FAIL;
     265             :                 }
     266           0 :                 cands = BATselect(func_lang, func_tid, &(int){FUNC_LANG_SQL}, NULL, true, true, false, false);
     267           0 :                 bat_destroy(func_lang);
     268           0 :                 bat_destroy(func_tid);
     269           0 :                 if (cands == NULL) {
     270           0 :                         bat_destroy(b2);
     271           0 :                         bat_destroy(func_func);
     272           0 :                         return GDK_FAIL;
     273             :                 }
     274           0 :                 struct canditer ci;
     275           0 :                 canditer_init(&ci, func_func, cands);
     276           0 :                 BATiter ffi = bat_iterator_nolock(func_func);
     277           0 :                 for (BUN p = 0; p < ci.ncand; p++) {
     278           0 :                         oid o = canditer_next(&ci);
     279           0 :                         const char *f = BUNtvar(ffi, o - func_func->hseqbase);
     280           0 :                         const char *e;
     281           0 :                         if (!strNil(f) &&
     282           0 :                                 (e = strstr(f, "external")) != NULL &&
     283           0 :                                 e > f && isspace((unsigned char) e[-1]) && isspace((unsigned char) e[8]) && strncmp(e + 9, "name", 4) == 0 && isspace((unsigned char) e[13]) &&
     284           0 :                                 BUNreplace(b2, o, &(int){FUNC_LANG_MAL}, false) != GDK_SUCCEED) {
     285           0 :                                 bat_destroy(b2);
     286           0 :                                 bat_destroy(func_func);
     287           0 :                                 return GDK_FAIL;
     288             :                         }
     289             :                 }
     290           0 :                 rc = replace_bat(lg, 2021, b2);
     291           0 :                 bat_destroy(b2);
     292           0 :                 if (rc != GDK_SUCCEED)
     293             :                         return rc;
     294             :         }
     295          16 :         if (store->catalog_version <= CATALOG_JUL2021) {
     296             :                 /* change the side_effects attribute in sys.functions for
     297             :                  * selected functions */
     298             : 
     299             :                 /* sys.functions i.e. deleted rows */
     300           0 :                 BAT *del_funcs = log_temp_descriptor(log_find_bat(lg, 2016));
     301           0 :                 if (del_funcs == NULL)
     302           0 :                         return GDK_FAIL;
     303           0 :                 BAT *func_tid = BATmaskedcands(0, BATcount(del_funcs), del_funcs, false);
     304           0 :                 bat_destroy(del_funcs);
     305             :                 /* sys.functions.schema_id */
     306           0 :                 BAT *func_schem = log_temp_descriptor(log_find_bat(lg, 2026));
     307           0 :                 if (func_tid == NULL || func_schem == NULL) {
     308           0 :                         bat_destroy(func_tid);
     309           0 :                         bat_destroy(func_schem);
     310           0 :                         return GDK_FAIL;
     311             :                 }
     312             :                 /* select * from sys.functions where schema_id = 2000 */
     313           0 :                 BAT *cands = BATselect(func_schem, func_tid, &(int) {2000}, NULL, true, true, false, false);
     314           0 :                 bat_destroy(func_schem);
     315           0 :                 bat_destroy(func_tid);
     316           0 :                 if (cands == NULL) {
     317             :                         return GDK_FAIL;
     318             :                 }
     319             :                 /* sys.functions.side_effect */
     320           0 :                 BAT *func_se = log_temp_descriptor(log_find_bat(lg, 2023));
     321           0 :                 if (func_se == NULL) {
     322           0 :                         bat_destroy(cands);
     323           0 :                         return GDK_FAIL;
     324             :                 }
     325             :                 /* make a copy that we can modify */
     326           0 :                 BAT *b = COLcopy(func_se, func_se->ttype, true, PERSISTENT);
     327           0 :                 bat_destroy(func_se);
     328           0 :                 if (b == NULL) {
     329           0 :                         bat_destroy(cands);
     330           0 :                         return GDK_FAIL;
     331             :                 }
     332           0 :                 func_se = b;
     333             :                 /* sys.functions.func */
     334           0 :                 BAT *func_func = log_temp_descriptor(log_find_bat(lg, 2019));
     335           0 :                 if (func_func == NULL) {
     336           0 :                         bat_destroy(cands);
     337           0 :                         bat_destroy(func_se);
     338           0 :                         return GDK_FAIL;
     339             :                 }
     340             :                 /* the functions we need to change to FALSE */
     341           0 :                 BAT *funcs = COLnew(0, TYPE_str, 1, TRANSIENT);
     342           0 :                 if (funcs == NULL ||
     343           0 :                         BUNappend(funcs, "sqlrand", false) != GDK_SUCCEED) {
     344           0 :                         bat_destroy(cands);
     345           0 :                         bat_destroy(func_se);
     346           0 :                         bat_destroy(func_func);
     347           0 :                         bat_destroy(funcs);
     348           0 :                         return GDK_FAIL;
     349             :                 }
     350             :                 /* select * from sys.functions where schema_id = 2000 and func in (...) */
     351           0 :                 b = BATintersect(func_func, funcs, cands, NULL, false, false, 1);
     352           0 :                 bat_destroy(funcs);
     353           0 :                 if (b == NULL) {
     354           0 :                         bat_destroy(cands);
     355           0 :                         bat_destroy(func_se);
     356           0 :                         bat_destroy(func_func);
     357           0 :                         return GDK_FAIL;
     358             :                 }
     359             :                 /* while we're at it, also change sys.env and sys.db_users to
     360             :                  * being without side effect (legacy from ancient databases) */
     361             :                 /* sys.functions.name */
     362           0 :                 BAT *func_name = log_temp_descriptor(log_find_bat(lg, 2018));
     363           0 :                 if (func_name == NULL) {
     364           0 :                         bat_destroy(cands);
     365           0 :                         bat_destroy(func_se);
     366           0 :                         bat_destroy(func_func);
     367           0 :                         bat_destroy(b);
     368           0 :                         return GDK_FAIL;
     369             :                 }
     370           0 :                 BAT *b2 = BATselect(func_name, cands, "env", NULL, true, true, false, false);
     371           0 :                 if (b2 == NULL || BATappend(b, b2, NULL, false) != GDK_SUCCEED) {
     372           0 :                         bat_destroy(cands);
     373           0 :                         bat_destroy(func_se);
     374           0 :                         bat_destroy(func_func);
     375           0 :                         bat_destroy(b);
     376           0 :                         bat_destroy(func_name);
     377           0 :                         bat_destroy(b2);
     378           0 :                         return GDK_FAIL;
     379             :                 }
     380           0 :                 bat_destroy(b2);
     381           0 :                 b2 = BATselect(func_name, cands, "db_users", NULL, true, true, false, false);
     382           0 :                 bat_destroy(func_name);
     383           0 :                 if (b2 == NULL || BATappend(b, b2, NULL, false) != GDK_SUCCEED) {
     384           0 :                         bat_destroy(cands);
     385           0 :                         bat_destroy(func_se);
     386           0 :                         bat_destroy(func_func);
     387           0 :                         bat_destroy(b);
     388           0 :                         bat_destroy(b2);
     389           0 :                         return GDK_FAIL;
     390             :                 }
     391           0 :                 bat_destroy(b2);
     392             : 
     393           0 :                 BAT *vals = BATconstant(0, TYPE_bit, &(bit) {FALSE}, BATcount(b), TRANSIENT);
     394           0 :                 if (vals == NULL) {
     395           0 :                         bat_destroy(cands);
     396           0 :                         bat_destroy(func_se);
     397           0 :                         bat_destroy(func_func);
     398           0 :                         bat_destroy(b);
     399           0 :                         return GDK_FAIL;
     400             :                 }
     401           0 :                 rc = BATreplace(func_se, b, vals, false);
     402           0 :                 bat_destroy(b);
     403           0 :                 bat_destroy(vals);
     404           0 :                 if (rc != GDK_SUCCEED) {
     405           0 :                         bat_destroy(cands);
     406           0 :                         bat_destroy(func_se);
     407           0 :                         bat_destroy(func_func);
     408           0 :                         return GDK_FAIL;
     409             :                 }
     410             :                 /* the functions we need to change to TRUE */
     411           0 :                 funcs = COLnew(0, TYPE_str, 5, TRANSIENT);
     412           0 :                 if (funcs == NULL ||
     413           0 :                         BUNappend(funcs, "copy_from", false) != GDK_SUCCEED ||
     414           0 :                         BUNappend(funcs, "next_value", false) != GDK_SUCCEED ||
     415           0 :                         BUNappend(funcs, "update_schemas", false) != GDK_SUCCEED ||
     416           0 :                         BUNappend(funcs, "update_tables", false) != GDK_SUCCEED) {
     417           0 :                         bat_destroy(cands);
     418           0 :                         bat_destroy(func_se);
     419           0 :                         bat_destroy(func_func);
     420           0 :                         bat_destroy(funcs);
     421           0 :                         return GDK_FAIL;
     422             :                 }
     423             :                 /* select * from sys.functions where schema_id = 2000 and func in (...) */
     424           0 :                 b = BATintersect(func_func, funcs, cands, NULL, false, false, 7);
     425           0 :                 bat_destroy(funcs);
     426           0 :                 bat_destroy(cands);
     427           0 :                 bat_destroy(func_func);
     428           0 :                 if (b == NULL) {
     429           0 :                         bat_destroy(func_se);
     430           0 :                         return GDK_FAIL;
     431             :                 }
     432           0 :                 vals = BATconstant(0, TYPE_bit, &(bit) {TRUE}, BATcount(b), TRANSIENT);
     433           0 :                 if (vals == NULL) {
     434           0 :                         bat_destroy(func_se);
     435           0 :                         bat_destroy(b);
     436           0 :                         return GDK_FAIL;
     437             :                 }
     438           0 :                 rc = BATreplace(func_se, b, vals, false);
     439           0 :                 bat_destroy(b);
     440           0 :                 bat_destroy(vals);
     441           0 :                 if (rc != GDK_SUCCEED) {
     442           0 :                         bat_destroy(func_se);
     443           0 :                         return GDK_FAIL;
     444             :                 }
     445             :                 /* replace old column with modified copy */
     446           0 :                 rc = replace_bat(lg, 2023, func_se);
     447           0 :                 bat_destroy(func_se);
     448           0 :                 if (rc != GDK_SUCCEED)
     449             :                         return rc;
     450             :         }
     451          16 :         if (store->catalog_version <= CATALOG_JUL2021) {
     452             :                 /* upgrade some columns in sys.sequences:
     453             :                  * if increment is zero, set it to one (see ChangeLog);
     454             :                  * if increment is greater than zero and maxvalue is zero,
     455             :                  * set maxvalue to GDK_lng_max;
     456             :                  * if increment is less than zero and minvalue is zero,
     457             :                  * set minvalue to GDK_lng_min */
     458             : 
     459             :                 /* sys.sequences i.e. deleted rows */
     460           0 :                 BAT *del_seqs = log_temp_descriptor(log_find_bat(lg, 2037));
     461           0 :                 if (del_seqs == NULL)
     462           0 :                         return GDK_FAIL;
     463           0 :                 BAT *seq_tid = BATmaskedcands(0, BATcount(del_seqs), del_seqs, false);
     464           0 :                 bat_destroy(del_seqs);
     465           0 :                 BAT *seq_min = log_temp_descriptor(log_find_bat(lg, 2042)); /* sys.sequences.minvalue */
     466           0 :                 BAT *seq_max = log_temp_descriptor(log_find_bat(lg, 2043)); /* sys.sequences.maxvalue */
     467           0 :                 BAT *seq_inc = log_temp_descriptor(log_find_bat(lg, 2044)); /* sys.sequences.increment */
     468           0 :                 if (seq_tid == NULL || seq_min == NULL || seq_max == NULL || seq_inc == NULL) {
     469           0 :                         bat_destroy(seq_tid);
     470           0 :                         bat_destroy(seq_min);
     471           0 :                         bat_destroy(seq_max);
     472           0 :                         bat_destroy(seq_inc);
     473           0 :                         return GDK_FAIL;
     474             :                 }
     475             :                 /* select * from sys.sequences where increment = 0 */
     476           0 :                 BAT *inczero = BATselect(seq_inc, seq_tid, &(lng){0}, NULL, false, true, false, false);
     477           0 :                 if (inczero == NULL) {
     478           0 :                         bat_destroy(seq_tid);
     479           0 :                         bat_destroy(seq_min);
     480           0 :                         bat_destroy(seq_max);
     481           0 :                         bat_destroy(seq_inc);
     482           0 :                         return GDK_FAIL;
     483             :                 }
     484           0 :                 if (BATcount(inczero) > 0) {
     485           0 :                         BAT *b = BATconstant(0, TYPE_lng, &(lng) {1}, BATcount(inczero), TRANSIENT);
     486           0 :                         if (b == NULL) {
     487           0 :                                 bat_destroy(seq_tid);
     488           0 :                                 bat_destroy(seq_min);
     489           0 :                                 bat_destroy(seq_max);
     490           0 :                                 bat_destroy(seq_inc);
     491           0 :                                 bat_destroy(inczero);
     492           0 :                                 return GDK_FAIL;
     493             :                         }
     494           0 :                         BAT *b2 = COLcopy(seq_inc, seq_inc->ttype, true, PERSISTENT);
     495           0 :                         rc = GDK_FAIL;
     496           0 :                         if (b2 == NULL)
     497           0 :                                 rc = BATreplace(b2, inczero, b, false);
     498           0 :                         bat_destroy(b);
     499           0 :                         if (rc != GDK_SUCCEED) {
     500           0 :                                 bat_destroy(b2);
     501           0 :                                 bat_destroy(seq_tid);
     502           0 :                                 bat_destroy(seq_min);
     503           0 :                                 bat_destroy(seq_max);
     504           0 :                                 bat_destroy(seq_inc);
     505           0 :                                 bat_destroy(inczero);
     506           0 :                                 return GDK_FAIL;
     507             :                         }
     508           0 :                         rc = replace_bat(lg, 2044, b2);
     509           0 :                         bat_destroy(seq_inc);
     510           0 :                         seq_inc = b2;
     511           0 :                         if (rc != GDK_SUCCEED) {
     512           0 :                                 bat_destroy(seq_tid);
     513           0 :                                 bat_destroy(seq_min);
     514           0 :                                 bat_destroy(seq_max);
     515           0 :                                 bat_destroy(seq_inc);
     516           0 :                                 bat_destroy(inczero);
     517           0 :                                 return rc;
     518             :                         }
     519             :                 }
     520           0 :                 bat_destroy(inczero);
     521             :                 /* select * from sys.sequences where increment > 0 */
     522           0 :                 BAT *incpos = BATselect(seq_inc, seq_tid, &(lng){0}, &lng_nil, false, true, false, false);
     523           0 :                 bat_destroy(seq_inc);
     524           0 :                 if (incpos == NULL) {
     525           0 :                         bat_destroy(seq_tid);
     526           0 :                         bat_destroy(seq_min);
     527           0 :                         bat_destroy(seq_max);
     528           0 :                         return GDK_FAIL;
     529             :                 }
     530             :                 /* select * from sys.sequences where increment > 0 and maxvalue = 0 */
     531           0 :                 BAT *cands = BATselect(seq_max, incpos, &(lng) {0}, NULL, true, true, false, false);
     532           0 :                 bat_destroy(incpos);
     533           0 :                 if (cands == NULL) {
     534           0 :                         bat_destroy(seq_tid);
     535           0 :                         bat_destroy(seq_min);
     536           0 :                         bat_destroy(seq_max);
     537           0 :                         return GDK_FAIL;
     538             :                 }
     539           0 :                 if (BATcount(cands) > 0) {
     540           0 :                         BAT *b = BATconstant(0, TYPE_lng, &(lng){GDK_lng_max}, BATcount(cands), TRANSIENT);
     541           0 :                         BAT *b2 = COLcopy(seq_max, seq_max->ttype, true, PERSISTENT);
     542           0 :                         rc = GDK_FAIL;
     543           0 :                         if (b != NULL && b2 != NULL)
     544           0 :                                 rc = BATreplace(b2, cands, b, false);
     545           0 :                         bat_destroy(b);
     546           0 :                         if (rc == GDK_SUCCEED)
     547           0 :                                 rc = replace_bat(lg, 2043, b2);
     548           0 :                         bat_destroy(b2);
     549           0 :                         if (rc != GDK_SUCCEED) {
     550           0 :                                 bat_destroy(cands);
     551           0 :                                 bat_destroy(seq_tid);
     552           0 :                                 bat_destroy(seq_min);
     553           0 :                                 bat_destroy(seq_max);
     554           0 :                                 return rc;
     555             :                         }
     556             :                 }
     557           0 :                 bat_destroy(seq_max);
     558           0 :                 bat_destroy(cands);
     559             :                 /* select * from sys.sequences where increment < 0 */
     560           0 :                 BAT *incneg = BATselect(seq_inc, seq_tid, &lng_nil, &(lng){0}, false, true, false, false);
     561           0 :                 bat_destroy(seq_tid);
     562             :                 /* select * from sys.sequences where increment < 0 and minvalue = 0 */
     563           0 :                 cands = BATselect(seq_min, incneg, &(lng) {0}, NULL, true, true, false, false);
     564           0 :                 bat_destroy(incneg);
     565           0 :                 if (cands == NULL) {
     566           0 :                         bat_destroy(seq_min);
     567           0 :                         return GDK_FAIL;
     568             :                 }
     569           0 :                 if (BATcount(cands) > 0) {
     570           0 :                         BAT *b = BATconstant(0, TYPE_lng, &(lng){GDK_lng_min}, BATcount(cands), TRANSIENT);
     571           0 :                         BAT *b2 = COLcopy(seq_min, seq_min->ttype, true, PERSISTENT);
     572           0 :                         rc = GDK_FAIL;
     573           0 :                         if (b != NULL && b2 != NULL)
     574           0 :                                 rc = BATreplace(b2, cands, b, false);
     575           0 :                         bat_destroy(b);
     576           0 :                         if (rc == GDK_SUCCEED)
     577           0 :                                 rc = replace_bat(lg, 2042, b2);
     578           0 :                         bat_destroy(b2);
     579           0 :                         if (rc != GDK_SUCCEED) {
     580           0 :                                 bat_destroy(cands);
     581           0 :                                 bat_destroy(seq_min);
     582           0 :                                 return rc;
     583             :                         }
     584             :                 }
     585           0 :                 bat_destroy(seq_min);
     586           0 :                 bat_destroy(cands);
     587             :         }
     588             : #endif
     589             : 
     590             : #ifdef CATALOG_JAN2022
     591          16 :         if (store->catalog_version <= CATALOG_JAN2022) {
     592             :                 /* GRANT SELECT ON sys.db_user_info TO monetdb;
     593             :                  * except the grantor is 0 instead of user monetdb
     594             :                  *
     595             :                  * we need to find the IDs of the sys.db_user_info table and of
     596             :                  * the sys.privileges table and its columns since none of these
     597             :                  * have fixed IDs */
     598           0 :                 BAT *b = log_temp_descriptor(log_find_bat(lg, 2067)); /* sys._tables */
     599           0 :                 if (b == NULL)
     600           0 :                         return GDK_FAIL;
     601           0 :                 BAT *del_tabs = BATmaskedcands(0, BATcount(b), b, false);
     602           0 :                 bat_destroy(b);
     603           0 :                 if (del_tabs == NULL)
     604             :                         return GDK_FAIL;
     605           0 :                 b = log_temp_descriptor(log_find_bat(lg, 2076)); /* sys._columns */
     606           0 :                 if (b == NULL) {
     607           0 :                         bat_destroy(del_tabs);
     608           0 :                         return GDK_FAIL;
     609             :                 }
     610           0 :                 BAT *del_cols = BATmaskedcands(0, BATcount(b), b, false);
     611           0 :                 bat_destroy(b);
     612           0 :                 b = log_temp_descriptor(log_find_bat(lg, 2070)); /* sys._tables.schema_id */
     613           0 :                 if (del_cols == NULL || b == NULL) {
     614           0 :                         bat_destroy(del_cols);
     615           0 :                         bat_destroy(b);
     616           0 :                         bat_destroy(del_tabs);
     617           0 :                         return GDK_FAIL;
     618             :                 }
     619           0 :                 BAT *cands = BATselect(b, del_tabs, &(int) {2000}, NULL, true, true, false, false);
     620           0 :                 bat_destroy(b);
     621           0 :                 bat_destroy(del_tabs);
     622             :                 /* cands contains undeleted rows from sys._tables for tables in
     623             :                  * sys schema */
     624           0 :                 BAT *tabnme = log_temp_descriptor(log_find_bat(lg, 2069)); /* sys._tables.name */
     625           0 :                 if (cands == NULL || tabnme == NULL) {
     626           0 :                         bat_destroy(cands);
     627           0 :                         bat_destroy(tabnme);
     628           0 :                         bat_destroy(del_cols);
     629           0 :                         return GDK_FAIL;
     630             :                 }
     631           0 :                 b = BATselect(tabnme, cands, "db_user_info", NULL, true, true, false, false);
     632           0 :                 if (b == NULL) {
     633           0 :                         bat_destroy(cands);
     634           0 :                         bat_destroy(tabnme);
     635           0 :                         bat_destroy(del_cols);
     636           0 :                         return GDK_FAIL;
     637             :                 }
     638           0 :                 oid dbpos = BUNtoid(b, 0);
     639           0 :                 bat_destroy(b);
     640           0 :                 b = BATselect(tabnme, cands, "privileges", NULL, true, true, false, false);
     641           0 :                 bat_destroy(tabnme);
     642           0 :                 bat_destroy(cands);
     643           0 :                 BAT *tabid = log_temp_descriptor(log_find_bat(lg, 2068)); /* sys._tables.id */
     644           0 :                 if (b == NULL || tabid == NULL) {
     645           0 :                         bat_destroy(b);
     646           0 :                         bat_destroy(tabid);
     647           0 :                         bat_destroy(del_cols);
     648           0 :                         return GDK_FAIL;
     649             :                 }
     650           0 :                 int dbid = ((int *) tabid->theap->base)[dbpos];
     651           0 :                 int prid = ((int *) tabid->theap->base)[BUNtoid(b, 0)];
     652           0 :                 BAT *coltid = log_temp_descriptor(log_find_bat(lg, 2082)); /* sys._columns.table_id */
     653           0 :                 if (coltid == NULL) {
     654           0 :                         bat_destroy(b);
     655           0 :                         bat_destroy(del_cols);
     656           0 :                         bat_destroy(tabid);
     657           0 :                         return GDK_FAIL;
     658             :                 }
     659           0 :                 BAT *b1;
     660           0 :                 rc = BATjoin(&b1, NULL, coltid, tabid, del_cols, b, false, 5);
     661           0 :                 bat_destroy(coltid);
     662           0 :                 bat_destroy(tabid);
     663           0 :                 bat_destroy(del_cols);
     664           0 :                 bat_destroy(b);
     665           0 :                 BAT *colnr = log_temp_descriptor(log_find_bat(lg, 2085)); /* sys._columns.number */
     666           0 :                 BAT *colid = log_temp_descriptor(log_find_bat(lg, 2077)); /* sys._columns.id */
     667           0 :                 if (rc != GDK_SUCCEED || colnr == NULL || colid == NULL) {
     668           0 :                         if (rc == GDK_SUCCEED)
     669           0 :                                 bat_destroy(b1);
     670           0 :                         bat_destroy(colnr);
     671           0 :                         bat_destroy(colid);
     672           0 :                         return GDK_FAIL;
     673             :                 }
     674             :                 int privids[5];
     675           0 :                 for (int i = 0; i < 5; i++) {
     676           0 :                         oid p = BUNtoid(b1, i);
     677           0 :                         privids[((int *) colnr->theap->base)[p]] = ((int *) colid->theap->base)[p];
     678             :                 }
     679           0 :                 bat_destroy(b1);
     680           0 :                 bat_destroy(colnr);
     681           0 :                 bat_destroy(colid);
     682           0 :                 rc = tabins(lg,
     683           0 :                                         prid, &(msk) {false}, /* sys.privileges */
     684             :                                         privids[0], &dbid, /* sys.privileges.obj_id */
     685           0 :                                         privids[1], &(int) {USER_MONETDB}, /* sys.privileges.auth_id */
     686           0 :                                         privids[2], &(int) {PRIV_SELECT}, /* sys.privileges.privileges */
     687           0 :                                         privids[3], &(int) {0}, /* sys.privileges.grantor */
     688           0 :                                         privids[4], &(int) {0}, /* sys.privileges.grantee */
     689             :                                         0);
     690           0 :                 if (rc != GDK_SUCCEED)
     691             :                         return rc;
     692             :         }
     693             : #endif
     694             : 
     695             : #ifdef CATALOG_SEP2022
     696          16 :         if (store->catalog_version <= CATALOG_SEP2022) {
     697             :                 /* new STRING column sys.keys.check */
     698           8 :                 BAT *b = log_temp_descriptor(log_find_bat(lg, 2088)); /* sys.keys.id */
     699           8 :                 if (b == NULL)
     700           0 :                         return GDK_FAIL;
     701           8 :                 BAT *check = BATconstant(b->hseqbase, TYPE_str, ATOMnilptr(TYPE_str), BATcount(b), PERSISTENT);
     702           8 :                 bat_destroy(b);
     703           8 :                 if (check == NULL)
     704             :                         return GDK_FAIL;
     705          16 :                 if ((check = BATsetaccess(check, BAT_READ)) == NULL ||
     706             :                                 /* 2165 is sys.keys.check */
     707          16 :                                 BUNappend(lg->catalog_id, &(int) {2165}, true) != GDK_SUCCEED ||
     708          16 :                                 BUNappend(lg->catalog_bid, &check->batCacheid, true) != GDK_SUCCEED ||
     709          16 :                                 BUNappend(lg->catalog_lid, &lng_nil, false) != GDK_SUCCEED ||
     710           8 :                                 BUNappend(lg->catalog_cnt, &(lng){BATcount(check)}, false) != GDK_SUCCEED
     711             :                 ) {
     712           0 :                         bat_destroy(check);
     713           0 :                         return GDK_FAIL;
     714             :                 }
     715           8 :                 BBPretain(check->batCacheid);
     716           8 :                 bat_destroy(check);
     717             : 
     718           8 :                 if (tabins(lg,
     719           8 :                                    2076, &(msk) {false},    /* sys._columns */
     720             :                                    /* 2165 is sys.keys.check */
     721           8 :                                    2077, &(int) {2165},             /* sys._columns.id */
     722             :                                    2078, "check",                     /* sys._columns.name */
     723             :                                    2079, "varchar",                   /* sys._columns.type */
     724           8 :                                    2080, &(int) {2048},             /* sys._columns.type_digits */
     725           8 :                                    2081, &(int) {0},                /* sys._columns.type_scale */
     726             :                                    /* 2087 is sys.keys */
     727           8 :                                    2082, &(int) {2087},             /* sys._columns.table_id */
     728             :                                    2083, str_nil,                       /* sys._columns.default */
     729           8 :                                    2084, &(bit) {TRUE},             /* sys._columns.null */
     730           8 :                                    2085, &(int) {6},                /* sys._columns.number */
     731             :                                    2086, str_nil,                       /* sys._columns.storage */
     732             :                                    0) != GDK_SUCCEED)
     733           0 :                         return GDK_FAIL;
     734           8 :                 if (tabins(lg,
     735           8 :                                    2076, &(msk) {false},    /* sys._columns */
     736             :                                    /* 2166 is tmp.keys.check */
     737           8 :                                    2077, &(int) {2166},             /* sys._columns.id */
     738             :                                    2078, "check",                     /* sys._columns.name */
     739             :                                    2079, "varchar",                   /* sys._columns.type */
     740           8 :                                    2080, &(int) {2048},             /* sys._columns.type_digits */
     741           8 :                                    2081, &(int) {0},                /* sys._columns.type_scale */
     742             :                                    /* 2135 is tmp.keys */
     743           8 :                                    2082, &(int) {2135},             /* sys._columns.table_id */
     744             :                                    2083, str_nil,                       /* sys._columns.default */
     745           8 :                                    2084, &(bit) {TRUE},             /* sys._columns.null */
     746           8 :                                    2085, &(int) {6},                /* sys._columns.number */
     747             :                                    2086, str_nil,                       /* sys._columns.storage */
     748             :                                    0) != GDK_SUCCEED)
     749           0 :                         return GDK_FAIL;
     750             :         }
     751             : #endif
     752             : 
     753             : #ifdef CATALOG_AUG2024
     754          16 :         if (store->catalog_version <= CATALOG_AUG2024) {
     755             :                 /* remove function sys.st_interiorrings and its arguments since
     756             :                  * it references the now removed type GEOMETRYA */
     757          16 :                 BAT *del_funcs = log_temp_descriptor(log_find_bat(lg, 2016)); /* sys.functions */
     758          16 :                 if (del_funcs == NULL)
     759           0 :                         return GDK_FAIL;
     760          16 :                 BAT *dels = BATmaskedcands(0, BATcount(del_funcs), del_funcs, false);
     761          16 :                 if (dels == NULL) {
     762           0 :                         bat_destroy(del_funcs);
     763           0 :                         return GDK_FAIL;
     764             :                 }
     765          16 :                 BAT *b = log_temp_descriptor(log_find_bat(lg, 2026)); /* sys.functions.schema_id */
     766          16 :                 if (b == NULL) {
     767           0 :                         bat_destroy(del_funcs);
     768           0 :                         bat_destroy(dels);
     769           0 :                         return GDK_FAIL;
     770             :                 }
     771             :                 /* select * from sys.functions where schema_id = 2000 */
     772          16 :                 BAT *cands = BATselect(b, dels, &(int) {2000}, NULL, true, true, false, false);
     773          16 :                 bat_destroy(b);
     774          16 :                 bat_destroy(dels);
     775          16 :                 b = log_temp_descriptor(log_find_bat(lg, 2018)); /* sys.functions.name */
     776          16 :                 if (cands == NULL || b == NULL) {
     777           0 :                         bat_destroy(del_funcs);
     778           0 :                         bat_destroy(cands);
     779           0 :                         bat_destroy(b);
     780           0 :                         return GDK_FAIL;
     781             :                 }
     782             :                 /* select * from sys.functions where schema_id = 2000 and name = 'st_interiorrings' */
     783          16 :                 BAT *funcs = BATselect(b, cands, "st_interiorrings", NULL, true, true, false, false);
     784          16 :                 bat_destroy(cands);
     785          16 :                 bat_destroy(b);
     786          16 :                 if (funcs == NULL) {
     787           0 :                         bat_destroy(del_funcs);
     788           0 :                         return GDK_FAIL;
     789             :                 }
     790             :                 /* here, funcs contains the BUNs for the function
     791             :                  * sys.st_interiorrings; if there are none, we're done */
     792          16 :                 if (BATcount(funcs) > 0) {
     793          16 :                         b = log_temp_descriptor(log_find_bat(lg, 2017)); /* sys.functions.id */
     794          16 :                         if (b == NULL) {
     795           0 :                                 bat_destroy(del_funcs);
     796           0 :                                 bat_destroy(funcs);
     797           0 :                                 return GDK_FAIL;
     798             :                         }
     799          16 :                         BAT *del_args = log_temp_descriptor(log_find_bat(lg, 2028)); /* sys.args */
     800          16 :                         if (del_args == NULL) {
     801           0 :                                 bat_destroy(del_funcs);
     802           0 :                                 bat_destroy(funcs);
     803           0 :                                 bat_destroy(b);
     804           0 :                                 return GDK_FAIL;
     805             :                         }
     806          16 :                         dels = BATmaskedcands(0, BATcount(del_args), del_args, false);
     807          16 :                         if (dels == NULL) {
     808           0 :                                 bat_destroy(del_funcs);
     809           0 :                                 bat_destroy(del_args);
     810           0 :                                 bat_destroy(funcs);
     811           0 :                                 bat_destroy(b);
     812           0 :                                 return GDK_FAIL;
     813             :                         }
     814          16 :                         BAT *a = log_temp_descriptor(log_find_bat(lg, 2030)); /* sys.args.func_id */
     815          16 :                         if (a == NULL) {
     816           0 :                                 bat_destroy(del_funcs);
     817           0 :                                 bat_destroy(del_args);
     818           0 :                                 bat_destroy(funcs);
     819           0 :                                 bat_destroy(b);
     820           0 :                                 return GDK_FAIL;
     821             :                         }
     822          16 :                         BAT *r1, *r2;
     823          16 :                         gdk_return rc;
     824             :                         /* find arguments to function sys.st_interiorrings */
     825          16 :                         rc = BATjoin(&r1, &r2, b, a, funcs, dels, false, 10);
     826          16 :                         bat_destroy(dels);
     827          16 :                         bat_destroy(b);
     828          16 :                         bat_destroy(a);
     829          16 :                         if (rc != GDK_SUCCEED) {
     830           0 :                                 bat_destroy(del_funcs);
     831           0 :                                 bat_destroy(del_args);
     832           0 :                                 bat_destroy(funcs);
     833           0 :                                 return GDK_FAIL;
     834             :                         }
     835          16 :                         b = COLcopy(del_funcs, del_funcs->ttype, true, PERSISTENT);
     836          16 :                         a = COLcopy(del_args, del_args->ttype, true, PERSISTENT);
     837          16 :                         bat_destroy(del_funcs);
     838          16 :                         bat_destroy(del_args);
     839          16 :                         if (b == NULL || a == NULL) {
     840           0 :                                 bat_destroy(funcs);
     841           0 :                                 bat_destroy(r1);
     842           0 :                                 bat_destroy(r2);
     843           0 :                                 return GDK_FAIL;
     844             :                         }
     845             :                         /* now set the deleted bit for all functions and all
     846             :                          * arguments that we've found (i.e. just the input and
     847             :                          * output arg for sys.st_interiorrings and the function
     848             :                          * itself) */
     849          16 :                         BUN p, q;
     850          48 :                         BATloop (r1, p, q) {
     851          32 :                                 oid o = BUNtoid(r1, p);
     852          32 :                                 if (BUNreplace(b, o, &(bool) {true}, false) != GDK_SUCCEED) {
     853           0 :                                         bat_destroy(funcs);
     854           0 :                                         bat_destroy(r1);
     855           0 :                                         bat_destroy(r2);
     856           0 :                                         bat_destroy(b);
     857           0 :                                         bat_destroy(a);
     858           0 :                                         return GDK_FAIL;
     859             :                                 }
     860          32 :                                 o = BUNtoid(r2, p);
     861          32 :                                 if (BUNreplace(a, o, &(bool) {true}, false) != GDK_SUCCEED) {
     862           0 :                                         bat_destroy(funcs);
     863           0 :                                         bat_destroy(r1);
     864           0 :                                         bat_destroy(r2);
     865           0 :                                         bat_destroy(b);
     866           0 :                                         bat_destroy(a);
     867           0 :                                         return GDK_FAIL;
     868             :                                 }
     869             :                         }
     870          16 :                         bat_destroy(r1);
     871          16 :                         bat_destroy(r2);
     872          16 :                         rc = replace_bat(lg, 2016, b);
     873          16 :                         if (rc == GDK_SUCCEED)
     874          16 :                                 rc = replace_bat(lg, 2028, a);
     875          16 :                         bat_destroy(b);
     876          16 :                         bat_destroy(a);
     877          16 :                         if (rc != GDK_SUCCEED) {
     878           0 :                                 bat_destroy(funcs);
     879           0 :                                 return rc;
     880             :                         }
     881             :                 }
     882          16 :                 bat_destroy(funcs);
     883             :         }
     884          16 :         if (store->catalog_version <= CATALOG_AUG2024) {
     885             :                 /* new TINYINT column sys.functions.order_specification */
     886          16 :                 BAT *ftype = log_temp_descriptor(log_find_bat(lg, 2022)); /* sys.functions.type (int) */
     887          16 :                 BAT *fname = log_temp_descriptor(log_find_bat(lg, 2018)); /* sys.functions.name (str) */
     888          16 :                 if (ftype == NULL || fname == NULL)
     889           0 :                         return GDK_FAIL;
     890          16 :                 bte zero = 0;
     891          16 :                 BAT *order_spec = BATconstant(ftype->hseqbase, TYPE_bte, &zero, BATcount(ftype), PERSISTENT);
     892             :                 /* update functions set order_specification=1 where type == aggr and name in ('group_concat', 'listagg', 'xmlagg')
     893             :                  * update functions set order_specification=2 where type == aggr and name = 'quantile' */
     894          16 :                 if (order_spec == NULL) {
     895           0 :                         bat_destroy(ftype);
     896           0 :                         bat_destroy(fname);
     897           0 :                         return GDK_FAIL;
     898             :                 }
     899          16 :                 bte *os = (bte*)Tloc(order_spec, 0);
     900          16 :                 int *ft = (int*)Tloc(ftype, 0);
     901          16 :                 BATiter fni = bat_iterator_nolock(fname);
     902       52888 :                 for(BUN b = 0; b < BATcount(ftype); b++) {
     903       52872 :                         if (ft[b] == F_AGGR) {
     904        3746 :                                 const char *f = BUNtvar(fni, b);
     905        3746 :                                 if (strcmp(f, "group_concat") == 0 || strcmp(f, "listagg") == 0 || strcmp(f, "xmlagg") == 0)
     906         160 :                                         os[b] = 1;
     907        3586 :                                 else if (strcmp(f, "quantile") == 0 || strcmp(f, "quantile_avg") == 0)
     908         400 :                                         os[b] = 2;
     909             :                         }
     910             :                 }
     911          16 :                 bat_destroy(ftype);
     912          16 :                 bat_destroy(fname);
     913          32 :                 if ((order_spec = BATsetaccess(order_spec, BAT_READ)) == NULL ||
     914             :                         /* 2167 is sys.functions.order_specification */
     915          32 :                         BUNappend(lg->catalog_id, &(int) {2167}, true) != GDK_SUCCEED ||
     916          32 :                         BUNappend(lg->catalog_bid, &order_spec->batCacheid, true) != GDK_SUCCEED ||
     917          32 :                         BUNappend(lg->catalog_lid, &lng_nil, false) != GDK_SUCCEED ||
     918          16 :                         BUNappend(lg->catalog_cnt, &(lng){BATcount(order_spec)}, false) != GDK_SUCCEED
     919             :                         ) {
     920           0 :                         bat_destroy(order_spec);
     921           0 :                         return GDK_FAIL;
     922             :                 }
     923          16 :                 BBPretain(order_spec->batCacheid);
     924          16 :                 bat_destroy(order_spec);
     925             : 
     926          16 :                 if (tabins(lg,
     927          16 :                                    2076, &(msk) {false},    /* sys._columns */
     928             :                                    /* 2167 is sys.functions.order_specification */
     929          16 :                                    2077, &(int) {2167},             /* sys._columns.id */
     930             :                                    2078, "order_specification",                       /* sys._columns.name */
     931             :                                    2079, "tinyint",                   /* sys._columns.type */
     932          16 :                                    2080, &(int) {7},                /* sys._columns.type_digits */
     933          16 :                                    2081, &(int) {0},                /* sys._columns.type_scale */
     934             :                                    /* 2016 is sys.functions */
     935          16 :                                    2082, &(int) {2016},             /* sys._columns.table_id */
     936             :                                    2083, str_nil,                       /* sys._columns.default */
     937          16 :                                    2084, &(bit) {TRUE},             /* sys._columns.null */
     938          16 :                                    2085, &(int) {12},               /* sys._columns.number */
     939             :                                    2086, str_nil,                       /* sys._columns.storage */
     940             :                                    0) != GDK_SUCCEED)
     941           0 :                         return GDK_FAIL;
     942             :         }
     943             : #endif
     944             : 
     945             :         return GDK_SUCCEED;
     946             : }
     947             : 
     948             : static int
     949         352 : bl_create(sqlstore *store, int debug, const char *logdir, int cat_version)
     950             : {
     951         352 :         if (store->logger)
     952             :                 return LOG_ERR;
     953         352 :         store->logger = log_create(debug, "sql", logdir, cat_version, (preversionfix_fptr)&bl_preversion, (postversionfix_fptr)&bl_postversion, store);
     954         352 :         if (store->logger)
     955             :                 return LOG_OK;
     956             :         return LOG_ERR;
     957             : }
     958             : 
     959             : static void
     960         351 : bl_destroy(sqlstore *store)
     961             : {
     962         351 :         logger *l = store->logger;
     963             : 
     964         351 :         store->logger = NULL;
     965         351 :         if (l)
     966         351 :                 log_destroy(l);
     967         351 : }
     968             : 
     969             : static int
     970        1483 : bl_flush(sqlstore *store, lng save_id)
     971             : {
     972        1483 :         if (store->logger)
     973        1483 :                 return log_flush(store->logger, save_id) == GDK_SUCCEED ? LOG_OK : LOG_ERR;
     974             :         return LOG_OK;
     975             : }
     976             : 
     977             : static int
     978        7215 : bl_activate(sqlstore *store)
     979             : {
     980        7215 :         if (store->logger)
     981        7215 :                 return log_activate(store->logger) == GDK_SUCCEED ? LOG_OK : LOG_ERR;
     982             :         return LOG_OK;
     983             : }
     984             : 
     985             : static int
     986        8514 : bl_changes(sqlstore *store)
     987             : {
     988        8514 :         return (int) MIN(log_changes(store->logger), GDK_int_max);
     989             : }
     990             : 
     991             : static int
     992         483 : bl_get_sequence(sqlstore *store, int seq, lng *id)
     993             : {
     994         483 :         return log_sequence(store->logger, seq, id);
     995             : }
     996             : 
     997             : static int
     998         352 : bl_log_isnew(sqlstore *store)
     999             : {
    1000         352 :         logger *bat_logger = store->logger;
    1001         352 :         if (BATcount(bat_logger->catalog_bid) > 10) {
    1002         125 :                 return 0;
    1003             :         }
    1004             :         return 1;
    1005             : }
    1006             : 
    1007             : static int
    1008       62457 : bl_tstart(sqlstore *store, bool flush, ulng *log_file_id)
    1009             : {
    1010       62457 :         return log_tstart(store->logger, flush, log_file_id) == GDK_SUCCEED ? LOG_OK : LOG_ERR;
    1011             : }
    1012             : 
    1013             : static int
    1014       62456 : bl_tend(sqlstore *store)
    1015             : {
    1016       62456 :         return log_tend(store->logger) == GDK_SUCCEED ? LOG_OK : LOG_ERR;
    1017             : }
    1018             : 
    1019             : static int
    1020       62456 : bl_tflush(sqlstore *store, ulng log_file_id, ulng commit_ts)
    1021             : {
    1022       62456 :         return log_tflush(store->logger, log_file_id, commit_ts) == GDK_SUCCEED ? LOG_OK : LOG_ERR;
    1023             : }
    1024             : 
    1025             : static int
    1026        6940 : bl_sequence(sqlstore *store, int seq, lng id)
    1027             : {
    1028        6940 :         return log_tsequence(store->logger, seq, id) == GDK_SUCCEED ? LOG_OK : LOG_ERR;
    1029             : }
    1030             : 
    1031             : /* Write a plan entry to copy part of the given file.
    1032             :  * That part of the file must remain unchanged until the plan is executed.
    1033             :  */
    1034             : __attribute__((__warn_unused_result__))
    1035             : static gdk_return
    1036        1035 : snapshot_lazy_copy_file(stream *plan, const char *name, uint64_t extent)
    1037             : {
    1038        1035 :         if (mnstr_printf(plan, "c %" PRIu64 " %s\n", extent, name) < 0) {
    1039           0 :                 GDKerror("%s", mnstr_peek_error(plan));
    1040           0 :                 return GDK_FAIL;
    1041             :         }
    1042             :         return GDK_SUCCEED;
    1043             : }
    1044             : 
    1045             : /* Write a plan entry to write the current contents of the given file.
    1046             :  * The contents are included in the plan so the source file is allowed to
    1047             :  * change in the mean time.
    1048             :  */
    1049             : __attribute__((__warn_unused_result__))
    1050             : static gdk_return
    1051          10 : snapshot_immediate_copy_file(stream *plan, const char *path, const char *name)
    1052             : {
    1053          10 :         gdk_return ret = GDK_FAIL;
    1054          10 :         const size_t bufsize = 64 * 1024;
    1055          10 :         struct stat statbuf;
    1056          10 :         char *buf = NULL;
    1057          10 :         stream *s = NULL;
    1058          10 :         size_t to_copy;
    1059             : 
    1060          10 :         if (MT_stat(path, &statbuf) < 0) {
    1061           0 :                 GDKsyserror("stat failed on %s", path);
    1062           0 :                 goto end;
    1063             :         }
    1064          10 :         to_copy = (size_t) statbuf.st_size;
    1065             : 
    1066          10 :         s = open_rstream(path);
    1067          10 :         if (!s) {
    1068           0 :                 GDKerror("%s", mnstr_peek_error(NULL));
    1069           0 :                 goto end;
    1070             :         }
    1071             : 
    1072          10 :         buf = GDKmalloc(bufsize);
    1073          10 :         if (!buf) {
    1074           0 :                 GDKerror("GDKmalloc failed");
    1075           0 :                 goto end;
    1076             :         }
    1077             : 
    1078          10 :         if (mnstr_printf(plan, "w %zu %s\n", to_copy, name) < 0) {
    1079           0 :                 GDKerror("%s", mnstr_peek_error(plan));
    1080           0 :                 goto end;
    1081             :         }
    1082             : 
    1083          20 :         while (to_copy > 0) {
    1084          10 :                 size_t chunk = (to_copy <= bufsize) ? to_copy : bufsize;
    1085          10 :                 ssize_t bytes_read = mnstr_read(s, buf, 1, chunk);
    1086          10 :                 if (bytes_read < 0) {
    1087           0 :                         GDKerror("Reading bytes of component %s failed: %s", path, mnstr_peek_error(s));
    1088           0 :                         goto end;
    1089          10 :                 } else if (bytes_read < (ssize_t) chunk) {
    1090           0 :                         GDKerror("Read only %zu/%zu bytes of component %s: %s", (size_t) bytes_read, chunk, path, mnstr_peek_error(s));
    1091           0 :                         goto end;
    1092             :                 }
    1093             : 
    1094          10 :                 ssize_t bytes_written = mnstr_write(plan, buf, 1, chunk);
    1095          10 :                 if (bytes_written < 0) {
    1096           0 :                         GDKerror("Writing to plan failed: %s", mnstr_peek_error(plan));
    1097           0 :                         goto end;
    1098          10 :                 } else if (bytes_written < (ssize_t) chunk) {
    1099           0 :                         GDKerror("write to plan truncated");
    1100           0 :                         goto end;
    1101             :                 }
    1102          10 :                 to_copy -= chunk;
    1103             :         }
    1104             : 
    1105             :         ret = GDK_SUCCEED;
    1106          10 : end:
    1107          10 :         GDKfree(buf);
    1108          10 :         if (s)
    1109          10 :                 close_stream(s);
    1110          10 :         return ret;
    1111             : }
    1112             : 
    1113             : /* Add plan entries for all relevant files in the Write Ahead Log */
    1114             : __attribute__((__warn_unused_result__))
    1115             : static gdk_return
    1116           5 : snapshot_wal(logger *bat_logger, stream *plan, const char *db_dir)
    1117             : {
    1118           5 :         char log_file[FILENAME_MAX];
    1119           5 :         int len;
    1120             : 
    1121           5 :         len = snprintf(log_file, sizeof(log_file), "%s/%s%s", db_dir, bat_logger->dir, LOGFILE);
    1122           5 :         if (len == -1 || (size_t)len >= sizeof(log_file)) {
    1123           0 :                 GDKerror("Could not open %s, filename is too large", log_file);
    1124           0 :                 return GDK_FAIL;
    1125             :         }
    1126           5 :         if (snapshot_immediate_copy_file(plan, log_file, log_file + strlen(db_dir) + 1) != GDK_SUCCEED)
    1127             :                 return GDK_FAIL;
    1128             : 
    1129          15 :         for (ulng id = bat_logger->saved_id+1; id <= bat_logger->id; id++) {
    1130          10 :                 struct stat statbuf;
    1131             : 
    1132          10 :                 len = snprintf(log_file, sizeof(log_file), "%s/%s%s." LLFMT, db_dir, bat_logger->dir, LOGFILE, id);
    1133          10 :                 if (len == -1 || (size_t)len >= sizeof(log_file)) {
    1134           0 :                         GDKerror("Could not open %s, filename is too large", log_file);
    1135           0 :                         return GDK_FAIL;
    1136             :                 }
    1137          10 :                 if (MT_stat(log_file, &statbuf) == 0) {
    1138          10 :                         if (snapshot_lazy_copy_file(plan, log_file + strlen(db_dir) + 1, statbuf.st_size) != GDK_SUCCEED)
    1139             :                                 return GDK_FAIL;
    1140             :                 } else {
    1141           0 :                         GDKerror("Could not open %s", log_file);
    1142           0 :                         return GDK_FAIL;
    1143             :                 }
    1144             :         }
    1145             :         return GDK_SUCCEED;
    1146             : }
    1147             : 
    1148             : __attribute__((__warn_unused_result__))
    1149             : static gdk_return
    1150        1605 : snapshot_heap(stream *plan, const char *db_dir, bat batid, const char *filename, const char *suffix, uint64_t extent)
    1151             : {
    1152        1605 :         char path1[FILENAME_MAX];
    1153        1605 :         char path2[FILENAME_MAX];
    1154        1605 :         const size_t offset = strlen(db_dir) + 1;
    1155        1605 :         struct stat statbuf;
    1156        1605 :         int len;
    1157             : 
    1158        1605 :         if (extent == 0) {
    1159             :                 /* nothing to copy */
    1160             :                 return GDK_SUCCEED;
    1161             :         }
    1162             :         // first check the backup dir
    1163        1025 :         len = snprintf(path1, FILENAME_MAX, "%s/%s/%o.%s", db_dir, BAKDIR, (int) batid, suffix);
    1164        1025 :         if (len == -1 || len >= FILENAME_MAX) {
    1165           0 :                 path1[FILENAME_MAX - 1] = '\0';
    1166           0 :                 GDKerror("Could not open %s, filename is too large", path1);
    1167           0 :                 return GDK_FAIL;
    1168             :         }
    1169        1025 :         if (MT_stat(path1, &statbuf) == 0) {
    1170           0 :                 return snapshot_lazy_copy_file(plan, path1 + offset, extent);
    1171             :         }
    1172        1025 :         if (errno != ENOENT) {
    1173           0 :                 GDKsyserror("Error stat'ing %s", path1);
    1174           0 :                 return GDK_FAIL;
    1175             :         }
    1176             : 
    1177             :         // then check the regular location
    1178        1025 :         len = snprintf(path2, FILENAME_MAX, "%s/%s/%s.%s", db_dir, BATDIR, filename, suffix);
    1179        1025 :         if (len == -1 || len >= FILENAME_MAX) {
    1180           0 :                 path2[FILENAME_MAX - 1] = '\0';
    1181           0 :                 GDKerror("Could not open %s, filename is too large", path2);
    1182           0 :                 return GDK_FAIL;
    1183             :         }
    1184        1025 :         if (MT_stat(path2, &statbuf) == 0) {
    1185        1025 :                 return snapshot_lazy_copy_file(plan, path2 + offset, extent);
    1186             :         }
    1187           0 :         if (errno != ENOENT) {
    1188           0 :                 GDKsyserror("Error stat'ing %s", path2);
    1189           0 :                 return GDK_FAIL;
    1190             :         }
    1191             : 
    1192           0 :         GDKerror("One of %s and %s must exist", path1, path2);
    1193           0 :         return GDK_FAIL;
    1194             : }
    1195             : 
    1196             : /* Add plan entries for all persistent BATs by looping over the BBP.dir.
    1197             :  * Also include the BBP.dir itself.
    1198             :  */
    1199             : __attribute__((__warn_unused_result__))
    1200             : static gdk_return
    1201           5 : snapshot_bats(stream *plan, const char *db_dir)
    1202             : {
    1203           5 :         char bbpdir[FILENAME_MAX];
    1204           5 :         FILE *fp = NULL;
    1205           5 :         int len;
    1206           5 :         gdk_return ret = GDK_FAIL;
    1207           5 :         int lineno = 0;
    1208           5 :         bat bbpsize = 0;
    1209           5 :         lng logno;
    1210           5 :         unsigned bbpversion;
    1211             : 
    1212           5 :         len = snprintf(bbpdir, FILENAME_MAX, "%s/%s/%s", db_dir, BAKDIR, "BBP.dir");
    1213           5 :         if (len == -1 || len >= FILENAME_MAX) {
    1214           0 :                 GDKerror("Could not open %s, filename is too large", bbpdir);
    1215           0 :                 return GDK_FAIL;
    1216             :         }
    1217           5 :         ret = snapshot_immediate_copy_file(plan, bbpdir, bbpdir + strlen(db_dir) + 1);
    1218           5 :         if (ret != GDK_SUCCEED)
    1219             :                 return ret;
    1220             : 
    1221             :         // Open the catalog and parse the header
    1222           5 :         fp = fopen(bbpdir, "r");
    1223           5 :         if (fp == NULL) {
    1224           0 :                 GDKerror("Could not open %s for reading: %s", bbpdir, mnstr_peek_error(NULL));
    1225           0 :                 return GDK_FAIL;
    1226             :         }
    1227           5 :         bbpversion = BBPheader(fp, &lineno, &bbpsize, &logno, false);
    1228           5 :         if (bbpversion == 0)
    1229           0 :                 goto end;
    1230           5 :         assert(bbpversion == GDKLIBRARY);
    1231             : 
    1232        1265 :         for (;;) {
    1233        1270 :                 BAT b;
    1234        1270 :                 Heap h;
    1235        1270 :                 Heap vh;
    1236        1270 :                 vh = h = (Heap) {
    1237             :                         .free = 0,
    1238             :                 };
    1239        1270 :                 b = (BAT) {
    1240             :                         .theap = &h,
    1241             :                         .tvheap = &vh,
    1242             :                 };
    1243        1270 :                 char *options;
    1244        1270 :                 char filename[sizeof(BBP_physical(0))];
    1245        1270 :                 char batname[129];
    1246             : #ifdef GDKLIBRARY_HASHASH
    1247        1270 :                 int hashash;
    1248             : #endif
    1249             : 
    1250        1270 :                 switch (BBPreadBBPline(fp, bbpversion, &lineno, &b,
    1251             : #ifdef GDKLIBRARY_HASHASH
    1252             :                                                            &hashash,
    1253             : #endif
    1254             :                                                            batname, filename, &options)) {
    1255           5 :                 case 0:
    1256             :                         /* end of file */
    1257           5 :                         fclose(fp);
    1258           5 :                         return GDK_SUCCEED;
    1259             :                 case 1:
    1260             :                         /* successfully read an entry */
    1261        1265 :                         break;
    1262           0 :                 default:
    1263             :                         /* error */
    1264           0 :                         fclose(fp);
    1265           0 :                         return GDK_FAIL;
    1266             :                 }
    1267             : #ifdef GDKLIBRARY_HASHASH
    1268        1265 :                 assert(hashash == 0);
    1269             : #endif
    1270        1265 :                 if (ATOMvarsized(b.ttype)) {
    1271         340 :                         ret = snapshot_heap(plan, db_dir, b.batCacheid, filename, "theap", b.tvheap->free);
    1272         340 :                         if (ret != GDK_SUCCEED)
    1273           0 :                                 goto end;
    1274             :                 }
    1275        1265 :                 ret = snapshot_heap(plan, db_dir, b.batCacheid, filename, BATtailname(&b), b.theap->free);
    1276        1265 :                 if (ret != GDK_SUCCEED)
    1277           0 :                         goto end;
    1278             :         }
    1279             : 
    1280           0 : end:
    1281           0 :         if (fp) {
    1282           0 :                 fclose(fp);
    1283             :         }
    1284           0 :         return ret;
    1285             : }
    1286             : 
    1287             : __attribute__((__warn_unused_result__))
    1288             : static gdk_return
    1289           5 : snapshot_vaultkey(stream *plan, const char *db_dir)
    1290             : {
    1291           5 :         char path[FILENAME_MAX];
    1292           5 :         struct stat statbuf;
    1293             : 
    1294           5 :         int len = snprintf(path, FILENAME_MAX, "%s/.vaultkey", db_dir);
    1295           5 :         if (len == -1 || len >= FILENAME_MAX) {
    1296           0 :                 path[FILENAME_MAX - 1] = '\0';
    1297           0 :                 GDKerror("Could not open %s, filename is too large", path);
    1298           0 :                 return GDK_FAIL;
    1299             :         }
    1300           5 :         if (MT_stat(path, &statbuf) == 0) {
    1301           0 :                 return snapshot_lazy_copy_file(plan, ".vaultkey", statbuf.st_size);
    1302             :         }
    1303           5 :         if (errno == ENOENT) {
    1304             :                 // No .vaultkey? Fine.
    1305             :                 return GDK_SUCCEED;
    1306             :         }
    1307             : 
    1308           0 :         GDKsyserror("Error stat'ing %s", path);
    1309           0 :         return GDK_FAIL;
    1310             : }
    1311             : 
    1312             : static gdk_return
    1313           5 : bl_snapshot(sqlstore *store, stream *plan)
    1314             : {
    1315           5 :         logger *bat_logger = store->logger;
    1316           5 :         gdk_return ret;
    1317           5 :         char db_dir[MAXPATH];
    1318           5 :         size_t db_dir_len;
    1319             : 
    1320             :         // Farm 0 is always the persistent farm.
    1321           5 :         if (GDKfilepath(db_dir, sizeof(db_dir), 0, NULL, "", NULL) != GDK_SUCCEED)
    1322             :                 return GDK_FAIL;
    1323           5 :         db_dir_len = strlen(db_dir);
    1324           5 :         if (db_dir[db_dir_len - 1] == DIR_SEP)
    1325           5 :                 db_dir[db_dir_len - 1] = '\0';
    1326             : 
    1327          10 :         if (mnstr_printf(plan, "%s\n", db_dir) < 0 ||
    1328             :                 // Please monetdbd
    1329           5 :                 mnstr_printf(plan, "w 0 .uplog\n") < 0) {
    1330           0 :                 GDKerror("%s", mnstr_peek_error(plan));
    1331           0 :                 ret = GDK_FAIL;
    1332           0 :                 goto end;
    1333             :         }
    1334             : 
    1335           5 :         ret = snapshot_vaultkey(plan, db_dir);
    1336           5 :         if (ret != GDK_SUCCEED)
    1337           0 :                 goto end;
    1338             : 
    1339           5 :         ret = snapshot_bats(plan, db_dir);
    1340           5 :         if (ret != GDK_SUCCEED)
    1341           0 :                 goto end;
    1342             : 
    1343           5 :         ret = snapshot_wal(bat_logger, plan, db_dir);
    1344           5 :         if (ret != GDK_SUCCEED)
    1345             :                 goto end;
    1346             : 
    1347             :         ret = GDK_SUCCEED;
    1348             : end:
    1349             :         return ret;
    1350             : }
    1351             : 
    1352             : void
    1353         352 : bat_logger_init( logger_functions *lf )
    1354             : {
    1355         352 :         lf->create = bl_create;
    1356         352 :         lf->destroy = bl_destroy;
    1357         352 :         lf->flush = bl_flush;
    1358         352 :         lf->activate = bl_activate;
    1359         352 :         lf->changes = bl_changes;
    1360         352 :         lf->get_sequence = bl_get_sequence;
    1361         352 :         lf->log_isnew = bl_log_isnew;
    1362         352 :         lf->log_tstart = bl_tstart;
    1363         352 :         lf->log_tend = bl_tend;
    1364         352 :         lf->log_tflush = bl_tflush;
    1365         352 :         lf->log_tsequence = bl_sequence;
    1366         352 :         lf->get_snapshot_files = bl_snapshot;
    1367         352 : }

Generated by: LCOV version 1.14