From 32ec6ed57f9d3ce99a2387596e1c7bbd543059d7 Mon Sep 17 00:00:00 2001 From: Salil Chandra Date: Fri, 22 Oct 2021 19:43:23 +0000 Subject: [PATCH] Add partial datacopy support through csc2 Signed-off-by: Salil Chandra --- bdb/bdb_api.h | 8 +- bdb/bdb_int.h | 1 + bdb/bdb_verify.c | 29 +++- bdb/bdb_verify.h | 1 + bdb/cursor.c | 8 +- bdb/cursor_rowlocks.c | 3 +- bdb/file.c | 48 +++--- csc2/dynschemaload.h | 7 + csc2/macc.h | 8 +- csc2/macc_so.c | 161 ++++++++++++++++-- csc2/maccparse.y | 9 + db/comdb2.c | 4 +- db/comdb2.h | 5 +- db/constraints.c | 13 +- db/fdb_bend_sql.c | 8 +- db/glue.c | 8 +- db/indices.c | 31 ++-- db/macc_glue.c | 68 +++++++- db/osqlshadtbl.c | 14 +- db/sqlglue.c | 45 ++++- db/tag.c | 80 +++++++-- db/tag.h | 15 +- db/toblob.c | 29 +++- db/verify.c | 6 + docs/images/key-section.gif | Bin 11128 -> 15030 bytes docs/pages/programming/system_tables.md | 13 +- docs/pages/programming/table_schema.md | 4 + docs/src/sqlitegen/bubble-generator-data.tcl | 11 +- schemachange/sc_add_table.c | 4 +- schemachange/sc_logic.c | 4 +- schemachange/sc_schema.c | 8 +- schemachange/sc_struct.c | 4 +- sqlite/CMakeLists.txt | 1 + sqlite/ext/comdb2/comdb2systblInt.h | 1 + sqlite/ext/comdb2/keys.c | 9 +- sqlite/ext/comdb2/partial_datacopies.c | 98 +++++++++++ sqlite/ext/comdb2/tables.c | 2 + sqlite/src/comdb2build.c | 96 ++++++++++- tests/auth.test/t09.expected | 1 + tests/cdb2sql.test/t00.expected | 7 +- tests/comdb2sys.test/comdb2sys.expected | 17 +- .../t00_create_table.expected | 118 ++++++------- .../ddl_no_csc2.test/t01_alter_table.expected | 38 ++--- .../t02_create_index.expected | 24 +-- tests/instant_sc.test/t08.req | 2 +- tests/instant_sc.test/t12.req | 2 +- tests/partial_datacopy.test/Makefile | 8 + tests/partial_datacopy.test/runit | 6 + tests/partial_datacopy.test/t00.expected | 33 ++++ tests/partial_datacopy.test/t00.sql | 35 ++++ tests/partial_datacopy.test/t01.expected | 11 ++ tests/partial_datacopy.test/t01.sql | 11 ++ tests/partial_datacopy.test/t02.expected | 33 ++++ tests/partial_datacopy.test/t02.sql | 35 ++++ tests/partial_datacopy.test/t03.expected | 24 +++ tests/partial_datacopy.test/t03.sql | 20 +++ tests/partial_datacopy.test/t04.expected | 25 +++ tests/partial_datacopy.test/t04.sql | 20 +++ tests/partial_datacopy.test/t05.expected | 39 +++++ tests/partial_datacopy.test/t05.sql | 39 +++++ tests/partial_datacopy.test/t06.expected | 25 +++ tests/partial_datacopy.test/t06.sql | 21 +++ tests/partial_datacopy.test/t07.expected | 24 +++ tests/partial_datacopy.test/t07.sql | 21 +++ tests/partial_datacopy.test/t08.expected | 47 +++++ tests/partial_datacopy.test/t08.sql | 39 +++++ tests/partial_datacopy.test/t09.expected | 24 +++ tests/partial_datacopy.test/t09.sql | 21 +++ tests/partial_datacopy.test/t10.expected | 4 + tests/partial_datacopy.test/t10.sql | 19 +++ tests/partial_datacopy.test/t11.expected | 25 +++ tests/partial_datacopy.test/t11.sql | 21 +++ tests/partial_datacopy.test/t12.expected | 2 + tests/partial_datacopy.test/t12.sql | 16 ++ tests/partial_datacopy.test/t13.expected | 40 +++++ tests/partial_datacopy.test/t13.sql | 23 +++ tests/partial_datacopy.test/t14.expected | 22 +++ tests/partial_datacopy.test/t14.sql | 19 +++ tests/sc_partial_datacopy.test/Makefile | 8 + .../logicalsc.testopts | 1 + tests/sc_partial_datacopy.test/lrl.options | 3 + tests/sc_partial_datacopy.test/runit | 144 ++++++++++++++++ tests/userschema.test/t00.expected | 1 + tools/cdb2sql/cdb2sql.cpp | 2 +- 84 files changed, 1751 insertions(+), 233 deletions(-) create mode 100644 sqlite/ext/comdb2/partial_datacopies.c create mode 100644 tests/partial_datacopy.test/Makefile create mode 100755 tests/partial_datacopy.test/runit create mode 100644 tests/partial_datacopy.test/t00.expected create mode 100644 tests/partial_datacopy.test/t00.sql create mode 100644 tests/partial_datacopy.test/t01.expected create mode 100644 tests/partial_datacopy.test/t01.sql create mode 100644 tests/partial_datacopy.test/t02.expected create mode 100644 tests/partial_datacopy.test/t02.sql create mode 100644 tests/partial_datacopy.test/t03.expected create mode 100644 tests/partial_datacopy.test/t03.sql create mode 100644 tests/partial_datacopy.test/t04.expected create mode 100644 tests/partial_datacopy.test/t04.sql create mode 100644 tests/partial_datacopy.test/t05.expected create mode 100644 tests/partial_datacopy.test/t05.sql create mode 100644 tests/partial_datacopy.test/t06.expected create mode 100644 tests/partial_datacopy.test/t06.sql create mode 100644 tests/partial_datacopy.test/t07.expected create mode 100644 tests/partial_datacopy.test/t07.sql create mode 100644 tests/partial_datacopy.test/t08.expected create mode 100644 tests/partial_datacopy.test/t08.sql create mode 100644 tests/partial_datacopy.test/t09.expected create mode 100644 tests/partial_datacopy.test/t09.sql create mode 100644 tests/partial_datacopy.test/t10.expected create mode 100644 tests/partial_datacopy.test/t10.sql create mode 100644 tests/partial_datacopy.test/t11.expected create mode 100644 tests/partial_datacopy.test/t11.sql create mode 100644 tests/partial_datacopy.test/t12.expected create mode 100644 tests/partial_datacopy.test/t12.sql create mode 100644 tests/partial_datacopy.test/t13.expected create mode 100644 tests/partial_datacopy.test/t13.sql create mode 100644 tests/partial_datacopy.test/t14.expected create mode 100644 tests/partial_datacopy.test/t14.sql create mode 100644 tests/sc_partial_datacopy.test/Makefile create mode 100644 tests/sc_partial_datacopy.test/logicalsc.testopts create mode 100644 tests/sc_partial_datacopy.test/lrl.options create mode 100755 tests/sc_partial_datacopy.test/runit diff --git a/bdb/bdb_api.h b/bdb/bdb_api.h index 4bfc6ecb04..5d9ab7f01c 100644 --- a/bdb/bdb_api.h +++ b/bdb/bdb_api.h @@ -480,7 +480,7 @@ void bdb_free_cloned_handle_with_other_data_files(bdb_state_type *bdb_state); bdb_state_type * bdb_open_more(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int *bdberr); @@ -488,7 +488,7 @@ bdb_open_more(const char name[], const char dir[], int lrl, short numix, bdb_state_type * bdb_open_more_tran(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, tran_type *tran, uint32_t flags, int *bdberr); @@ -527,7 +527,7 @@ bdb_state_type *bdb_create_more_lite(const char name[], const char dir[], bdb_state_type * bdb_create(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int temp, int *bdberr); @@ -535,7 +535,7 @@ bdb_create(const char name[], const char dir[], int lrl, short numix, bdb_state_type * bdb_create_tran(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int temp, int *bdberr, tran_type *); diff --git a/bdb/bdb_int.h b/bdb/bdb_int.h index 0aedfa33c2..e99aae33b1 100644 --- a/bdb/bdb_int.h +++ b/bdb/bdb_int.h @@ -830,6 +830,7 @@ struct bdb_state_tag { short numix; /* number of indexes */ short ixlen[MAXINDEX]; /* size of each index */ signed char ixdta[MAXINDEX]; /* does this index contain the dta? */ + int ixdtalen[MAXINDEX]; /* dta len in bytes (0 if index does not contain the dta or is full datacopy) */ signed char ixcollattr[MAXINDEX]; /* does this index contain the column attributes? */ signed char ixnulls[MAXINDEX]; /*does this index contain any columns that diff --git a/bdb/bdb_verify.c b/bdb/bdb_verify.c index 877d2ecbf7..26dfd965f5 100644 --- a/bdb/bdb_verify.c +++ b/bdb/bdb_verify.c @@ -876,16 +876,19 @@ static int bdb_verify_key(verify_common_t *par, int ix, unsigned int lid) /* if dtacopy, does data payload in the key match the data * payload in the dta file? */ int expected_size; + int datacopy_size = bdb_state->ixdtalen[ix] > 0 ? bdb_state->ixdtalen[ix] : bdb_state->lrl; uint8_t *expected_data; - uint8_t datacopy_buffer[bdb_state->lrl]; + uint8_t datacopy_buffer[datacopy_size]; if (bdb_state->datacopy_odh) { int odhlen; unpack_index_odh(bdb_state, &dbt_data, &genid_right, datacopy_buffer, sizeof(datacopy_buffer), &odhlen, &ver); expected_size = odhlen; - par->vtag_callback(par->db_table, datacopy_buffer, - &expected_size, ver); + if (bdb_state->ixdtalen[ix] == 0) { // full datacopy + par->vtag_callback(par->db_table, datacopy_buffer, + &expected_size, ver); + } expected_data = datacopy_buffer; } else { expected_size = dbt_data.size - sizeof(genid); @@ -893,17 +896,29 @@ static int bdb_verify_key(verify_common_t *par, int ix, unsigned int lid) memcpy(&genid_right, (uint8_t *)dbt_data.data, sizeof(genid)); } - if (expected_size != bdb_state->lrl) { + if (expected_size != datacopy_size) { par->verify_status = 1; locprint(par, "!%016llx ix %d dtacpy payload wrong size expected %d " "got %d", - genid_flipped, ix, bdb_state->lrl, expected_size); + genid_flipped, ix, datacopy_size, expected_size); goto next_key; } - if (memcmp(expected_data, dbt_dta_check_data.data, - bdb_state->lrl)) { + char tail[datacopy_size]; + void *compared_data = dbt_dta_check_data.data; + if (bdb_state->ixdtalen[ix] > 0) { // partial datacopy + rc = par->partial_datacopy_callback(par->db_table, ix, dbt_dta_check_data.data, tail); + if (rc) { + par->verify_status = 1; + locprint(par, "!%016llx ix %d could not convert dta", genid_flipped); + goto next_key; + } + compared_data = tail; + } + + if (memcmp(expected_data, compared_data, + datacopy_size)) { par->verify_status = 1; locprint(par, "!%016llx ix %d dtacpy data mismatch", genid_flipped, ix); diff --git a/bdb/bdb_verify.h b/bdb/bdb_verify.h index 7e50e073aa..a6a92cab54 100644 --- a/bdb/bdb_verify.h +++ b/bdb/bdb_verify.h @@ -34,6 +34,7 @@ typedef struct { bdb_state_type *bdb_state; struct dbtable *db_table; const char *tablename; + int (*partial_datacopy_callback)(const struct dbtable *tbl, const int pd_ix, const void *inbuf, void *outbuf); int (*formkey_callback)(const struct dbtable *tbl, void *dta, void *blob_parm, int ix, void *keyout, int *keysz); int (*get_blob_sizes_callback)(const struct dbtable *tbl, void *dta, int blobs[16], diff --git a/bdb/cursor.c b/bdb/cursor.c index 5e7d27cf7b..6e20647abf 100644 --- a/bdb/cursor.c +++ b/bdb/cursor.c @@ -631,11 +631,12 @@ bdb_cursor_ifn_t *bdb_cursor_open( cur->idx = ixnum; cur->type = BDBC_IX; if (bdb_state->ixdta[ixnum]) { + int datacopy_size = bdb_state->ixdtalen[ixnum] > 0 ? bdb_state->ixdtalen[ixnum] : bdb_state->lrl; cur->datacopy = - malloc(bdb_state->lrl + 2 * sizeof(unsigned long long)); + malloc(datacopy_size + 2 * sizeof(unsigned long long)); if (!cur->datacopy) { logmsg(LOGMSG_ERROR, "%s: malloc %zu\n", __func__, - bdb_state->lrl + 2 * sizeof(unsigned long long)); + datacopy_size + 2 * sizeof(unsigned long long)); *bdberr = BDBERR_MALLOC; free(pcur_ifn); return NULL; @@ -6527,8 +6528,9 @@ static void *bdb_cursor_datacopy(bdb_cursor_ifn_t *cur) if (bdb_state->ondisk_header && bdb_state->datacopy_odh && (c->type == BDBC_DT || !is_genid_synthetic(c->genid))) { + int datacopy_size = bdb_state->ixdtalen[c->idx] > 0 ? bdb_state->ixdtalen[c->idx] : bdb_state->lrl; c->unpacked_datacopy = unpack_datacopy_odh( - cur, c->datacopy, bdb_state->lrl, from, size, &c->ver); + cur, c->datacopy, datacopy_size, from, size, &c->ver); } else { c->unpacked_datacopy = from; c->ver = c->state->version; diff --git a/bdb/cursor_rowlocks.c b/bdb/cursor_rowlocks.c index ec2a786ff8..23eacec284 100644 --- a/bdb/cursor_rowlocks.c +++ b/bdb/cursor_rowlocks.c @@ -2668,7 +2668,8 @@ int bdb_berkdb_rowlocks_init(bdb_berkdb_t *berkdb, DB *db, int *bdberr) r->keylen += sizeof(unsigned long long); r->dtalen = sizeof(unsigned long long); if (bdb_state->ixdta[cur->idx]) { - r->dtalen += bdb_state->lrl + (bdb_state->ondisk_header ? 7 : 0); + int datacopy_size = bdb_state->ixdtalen[cur->idx] > 0 ? bdb_state->ixdtalen[cur->idx] : bdb_state->lrl; + r->dtalen += datacopy_size + (bdb_state->ondisk_header ? 7 : 0); } r->keymem = malloc(r->keylen + 1); r->key = r->keymem; diff --git a/bdb/file.c b/bdb/file.c index f5bb81bf0f..9150e4f919 100644 --- a/bdb/file.c +++ b/bdb/file.c @@ -4531,11 +4531,12 @@ static int open_dbs_int(bdb_state_type *bdb_state, int iammaster, int upgrade, way to override this in the lrl file, we're gonna listen */ if (pagesize == 4096) { /* for datacopy indexes, use a potentially larger pagesize */ - if (bdb_state->ixdta[i]) + if (bdb_state->ixdta[i]) { + int datacopy_size = bdb_state->ixdtalen[i] > 0 ? bdb_state->ixdtalen[i] : bdb_state->lrl; pagesize = - calc_pagesize(bdb_state->attr->pagesizeix, bdb_state->lrl + bdb_state->ixlen[i]); + calc_pagesize(bdb_state->attr->pagesizeix, datacopy_size + bdb_state->ixlen[i]); /*else if (bdb_state->ixcollattr[i]) ignore this for now */ - else + } else pagesize = calc_pagesize(bdb_state->attr->pagesizeix, bdb_state->ixlen[i]); } @@ -5445,7 +5446,7 @@ static void bdb_blobmem_init_once(void) static bdb_state_type *bdb_open_int( int envonly, const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_attr_type *bdb_attr, bdb_callback_type *bdb_callback, void *usr_ptr, netinfo_type *netinfo, int upgrade, int create, int *bdberr, @@ -5684,6 +5685,11 @@ static bdb_state_type *bdb_open_int( else bdb_state->ixdta[i] = 0; + if (ixdtalen) + bdb_state->ixdtalen[i] = ixdtalen[i]; + else + bdb_state->ixdtalen[i] = 0; + if (ixcollattr) bdb_state->ixcollattr[i] = ixcollattr[i]; else @@ -6099,8 +6105,8 @@ bdb_state_type *bdb_open_env(const char name[], const char dir[], return bdb_open_int( 1, /* envonly */ - name, dir, 0, 0, NULL, NULL, NULL, NULL, - NULL, /* numix, ixlen, ixdups, ixrecnum, ixdta, ixcollattr */ + name, dir, 0, 0, NULL, NULL, NULL, NULL, NULL, + NULL, /* numix, ixlen, ixdups, ixrecnum, ixdta, ixdtalen, ixcollattr */ NULL, /* ixnulls */ 0, /* numdtafiles */ bdb_attr, /* bdb_attr */ @@ -6116,7 +6122,7 @@ bdb_state_type *bdb_open_env(const char name[], const char dir[], bdb_state_type * bdb_create_tran(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int temp, int *bdberr, tran_type *trans) @@ -6133,7 +6139,7 @@ bdb_create_tran(const char name[], const char dir[], int lrl, short numix, ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, ixdtalen, ixcollattr, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ @@ -6148,7 +6154,7 @@ bdb_create_tran(const char name[], const char dir[], int lrl, short numix, } else { ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, ixdtalen, ixcollattr, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ @@ -6168,7 +6174,7 @@ bdb_create_tran(const char name[], const char dir[], int lrl, short numix, bdb_state_type * bdb_open_more_int(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int *bdberr) @@ -6178,7 +6184,7 @@ bdb_open_more_int(const char name[], const char dir[], int lrl, short numix, *bdberr = BDBERR_NOERROR; ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, ixdtalen, ixcollattr, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ @@ -6194,13 +6200,13 @@ bdb_open_more_int(const char name[], const char dir[], int lrl, short numix, bdb_state_type * bdb_create(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int temp, int *bdberr) { return bdb_create_tran(name, dir, lrl, numix, ixlen, ixdups, ixrecnum, - ixdta, ixcollattr, ixnulls, numdtafiles, + ixdta, ixdtalen, ixcollattr, ixnulls, numdtafiles, parent_bdb_handle, temp, bdberr, NULL); } @@ -6209,7 +6215,7 @@ bdb_create(const char name[], const char dir[], int lrl, short numix, bdb_state_type * bdb_open_more(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, int *bdberr) { @@ -6221,7 +6227,7 @@ bdb_open_more(const char name[], const char dir[], int lrl, short numix, BDB_READLOCK("bdb_open_more"); ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, ixdtalen, ixcollattr, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ @@ -6241,7 +6247,7 @@ bdb_open_more(const char name[], const char dir[], int lrl, short numix, bdb_state_type * bdb_open_more_tran(const char name[], const char dir[], int lrl, short numix, const short ixlen[], const signed char ixdups[], - const signed char ixrecnum[], const signed char ixdta[], + const signed char ixrecnum[], const signed char ixdta[], const int ixdtalen[], const signed char ixcollattr[], const signed char ixnulls[], int numdtafiles, bdb_state_type *parent_bdb_handle, tran_type *tran, uint32_t flags, int *bdberr) @@ -6254,7 +6260,7 @@ bdb_open_more_tran(const char name[], const char dir[], int lrl, short numix, BDB_READLOCK("bdb_open_more_tran"); ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, ixlen, ixdups, ixrecnum, ixdta, ixdtalen, ixcollattr, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ @@ -6294,6 +6300,7 @@ bdb_state_type *bdb_open_more_lite(const char name[], const char dir[], int lrl, signed char ixdups[1] = {0}; signed char ixrecnum[1] = {0}; signed char ixdta[1] = {0}; + int ixdtalen[1] = {0}; signed char ixnulls[1] = {0}; short ixlen; @@ -6307,7 +6314,7 @@ bdb_state_type *bdb_open_more_lite(const char name[], const char dir[], int lrl, BDB_READLOCK("bdb_open_more_lite"); ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, &ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, &ixlen, ixdups, ixrecnum, ixdta, ixdtalen, NULL, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ @@ -6342,6 +6349,7 @@ bdb_state_type *bdb_open_more_queue(const char name[], const char dir[], NULL, /* ixdups */ NULL, /* ixrecnum */ NULL, /* ixdta */ + NULL, /* ixdtalen */ NULL, /* ixcollattr */ NULL, /* ixnulls */ 1, /* numdtafiles (berkdb queue file) */ @@ -6382,6 +6390,7 @@ bdb_state_type *bdb_create_queue_tran(tran_type *tran, const char name[], NULL, /* ixdups */ NULL, /* ixrecnum */ NULL, /* ixdta */ + NULL, /* ixdtalen */ NULL, /* ixcollattr */ NULL, /* ixnulls */ 1, /* numdtafiles (berkdb queue file) */ @@ -6418,6 +6427,7 @@ bdb_state_type *bdb_create_more_lite(const char name[], const char dir[], signed char ixdups[1] = {0}; signed char ixrecnum[1] = {0}; signed char ixdta[1] = {0}; + int ixdtalen[1] = {0}; signed char ixnulls[1] = {0}; short ixlen; @@ -6437,7 +6447,7 @@ bdb_state_type *bdb_create_more_lite(const char name[], const char dir[], } else { ret = bdb_open_int(0, /* envonly */ - name, dir, lrl, numix, &ixlen, ixdups, ixrecnum, ixdta, + name, dir, lrl, numix, &ixlen, ixdups, ixrecnum, ixdta, ixdtalen, NULL, ixnulls, numdtafiles, NULL, /* bdb_attr */ NULL, /* bdb_callback */ NULL, /* usr_ptr */ diff --git a/csc2/dynschemaload.h b/csc2/dynschemaload.h index 024eee34dc..74a73fda51 100644 --- a/csc2/dynschemaload.h +++ b/csc2/dynschemaload.h @@ -4,6 +4,11 @@ #include #include +struct partial_datacopy { + char *field; + struct partial_datacopy *next; +}; + enum fieldopttypes { FLDOPT_DBSTORE = 0, FLDOPT_DBLOAD = 1, @@ -39,6 +44,7 @@ int dyns_is_idx_dup(int index); int dyns_is_idx_recnum(int index); int dyns_is_idx_primary(int index); int dyns_is_idx_datacopy(int index); +int dyns_is_idx_partial_datacopy(int index); int dyns_is_idx_uniqnulls(int index); int dyns_get_idx_count(void); int dyns_get_idx_size(int index); @@ -57,6 +63,7 @@ int dyns_field_depth(int fidx, dpth_t *dpthinfo, int ndpthsinfo, int *ndpthout); int dyns_field_type(int fidx); int dyns_is_field_array(int fidx); int dyns_get_field_arr_dims(int fidx, int *dims, int ndims, int *nodims); +int dyns_get_idx_partial_datacopy(int index, struct partial_datacopy **partial_datacopy); int dyns_get_idx_tag(int index, char *tag, int tlen, char **where); /* calls to work with multiple tables */ diff --git a/csc2/macc.h b/csc2/macc.h index 98f0e4cfe2..e9300e4c7d 100644 --- a/csc2/macc.h +++ b/csc2/macc.h @@ -171,6 +171,7 @@ struct key { int exprtype; int exprarraysz; char *where; + struct partial_datacopy *pd; /* partial datacopy fields (if any) */ }; enum KEYFLAGS { @@ -183,7 +184,8 @@ enum INDEXFLAGS { RECNUMS = 0x00000002, /* index has key sequence numbers (COMDB2) */ PRIMARY = 0x00000004, DATAKEY = 0x00000008, /* key flag to indicate index has data */ - UNIQNULLS = 0x00000010 /* all NULL values are treated as UNIQUE */ + UNIQNULLS = 0x00000010, /* all NULL values are treated as UNIQUE */ + PARTIALDATAKEY = 0x00000020 /* key flag to indicate index has some data */ }; typedef struct macc_globals_t { @@ -201,6 +203,8 @@ typedef struct macc_globals_t { struct key *keys[MAXKEYS]; struct key *workkey; struct key *rngs[MAXRNGS]; + struct partial_datacopy *head_pd; + struct partial_datacopy *tail_pd; int keyixnum[MAXKEYS]; /* index # associated with a key */ int keyexprnum[MAXKEYS]; /* case number associated with a key */ int workkeyflag; /* work key's flag */ @@ -314,10 +318,12 @@ void key_setdup(); void key_setrecnums(void); void key_setprimary(void); void key_setdatakey(void); +void key_setpartialdatakey(void); void key_setuniqnulls(void); void reset_key_exprtype(void); void key_exprtype_add(int type, int arraysz); void key_piece_add(char *buf, int is_expr); +void datakey_piece_add(char *buf); void key_piece_setdescend(); char *strcpylower(char *c); int keysize(struct key *ck); diff --git a/csc2/macc_so.c b/csc2/macc_so.c index e5fff98010..6436e5c30e 100644 --- a/csc2/macc_so.c +++ b/csc2/macc_so.c @@ -909,9 +909,53 @@ void key_setprimary(void) void key_setdatakey(void) { + if (macc_globals->workkeyflag & PARTIALDATAKEY) { + csc2_error("Error at line %3d: CANNOT HAVE DATACOPY AND PARTIAL DATACOPY.\n", + current_line); + csc2_syntax_error("Error at line %3d: CANNOT HAVE DATACOPY AND PARTIAL DATACOPY.", + current_line); + any_errors++; + return; + } macc_globals->workkeyflag |= DATAKEY; } +void key_setpartialdatakey(void) +{ + if (macc_globals->workkeyflag & DATAKEY) { + csc2_error("Error at line %3d: CANNOT HAVE DATACOPY AND PARTIAL DATACOPY.\n", + current_line); + csc2_syntax_error("Error at line %3d: CANNOT HAVE DATACOPY AND PARTIAL DATACOPY.", + current_line); + any_errors++; + return; + } else if (macc_globals->workkeyflag & PARTIALDATAKEY) { + csc2_error("Error at line %3d: CANNOT HAVE MULTIPLE PARTIAL DATACOPIES.\n", + current_line); + csc2_syntax_error("Error at line %3d: CANNOT HAVE MULTIPLE PARTIAL DATACOPIES.", + current_line); + any_errors++; + return; + } + + // check for decimal columns (currently not supported) + struct table *tbl = &macc_globals->tables[macc_globals->ntables - 1]; + int type; + for (int i = 0; i < tbl->nsym; i++) { + type = tbl->sym[i].type; + if (type == T_DECIMAL32 || type == T_DECIMAL64 || type == T_DECIMAL128) { + csc2_error("Error at line %3d: CURRENTLY CANNOT HAVE PARTIAL DATACOPY WITH DECIMAL COLUMNS.\n", + current_line); + csc2_syntax_error("Error at line %3d: CURRENTLY CANNOT HAVE PARTIAL DATACOPY WITH DECIMAL COLUMNS.", + current_line); + any_errors++; + return; + } + } + + macc_globals->workkeyflag |= PARTIALDATAKEY; +} + void key_setuniqnulls(void) { CHECK_LEGACY_SCHEMA(1); @@ -923,6 +967,8 @@ void key_piece_clear() /* used by parser, clears work key */ macc_globals->workkey = 0; /* clear work key */ macc_globals->workkeyflag = 0; /* clear flag for work key */ macc_globals->workkeypieceflag = 0; /* clear key piece's flags */ + macc_globals->head_pd = 0; /* clear partial datacopy */ + macc_globals->tail_pd = 0; /* clear partial datacopy */ } void key_piece_setdescend() @@ -1111,6 +1157,19 @@ static void key_add_comn(int ix, char *tag, char *exprname, } else { macc_globals->keys[ii]->where = NULL; } + + if (macc_globals->workkeyflag & PARTIALDATAKEY) { + if (!macc_globals->head_pd) { + csc2_error("ERROR: PARTIAL DATACOPY FAILED\n"); + any_errors++; + return; + } + + macc_globals->keys[ii]->pd = macc_globals->head_pd; + } else { + macc_globals->keys[ii]->pd = NULL; + } + macc_globals->nkeys++; /* next key */ } @@ -1144,11 +1203,31 @@ void key_exprtype_add(int type, int arraysz) expridx_arraysz = arraysz; } +static int find_symbol(char *buf, int *tidx) { + char *tag = ONDISKTAG; + int i = getsymbol(tag, buf, tidx); + + if (i == -1) { + tag = (macc_globals->ntables > 1) ? ONDISKTAG : DEFAULTTAG; + i = getsymbol(tag, buf, tidx); + } + if (i == -1) { + csc2_error("Error at line %3d: SYMBOL NOT FOUND: %s.\n", + current_line, buf); + csc2_syntax_error("Error at line %3d: SYMBOL NOT FOUND: %s.", + current_line, buf); + csc2_error("IF IN MULTI-TABLE MODE MAKE SURE %s TAG IS DEFINED\n", + ONDISKTAG); + any_errors++; + } + return i; +} + void key_piece_add(char *buf, int is_expr) /* used by parser, adds a piece of a key */ { int el[6], rg[2], i, t, tidx = 0; - char *cp, *tag; + char *cp; if (is_expr) { CHECK_LEGACY_SCHEMA(1); @@ -1194,21 +1273,8 @@ void key_piece_add(char *buf, if (cp) *cp = 0; - tag = ONDISKTAG; - i = getsymbol(tag, buf, &tidx); - - if (i == -1) { - tag = (macc_globals->ntables > 1) ? ONDISKTAG : DEFAULTTAG; - i = getsymbol(tag, buf, &tidx); - } - if (i == -1) { - csc2_error("Error at line %3d: SYMBOL NOT FOUND: %s.\n", - current_line, buf); - csc2_syntax_error("Error at line %3d: SYMBOL NOT FOUND: %s.", - current_line, buf); - csc2_error("IF IN MULTI-TABLE MODE MAKE SURE %s TAG IS DEFINED\n", - ONDISKTAG); - any_errors++; + i = find_symbol(buf, &tidx); + if (i == -1) { // will error return; } else { struct table *tables = macc_globals->tables; @@ -1274,6 +1340,45 @@ void key_piece_add(char *buf, macc_globals->workkeypieceflag = 0; } +void datakey_piece_add(char *buf) { + int tidx = 0; + struct partial_datacopy *temp; + + strlower(buf, strlen(buf)); + int i = find_symbol(buf, &tidx); + if (i == -1) { // will error + return; + } + + // check if field already present + if (macc_globals->head_pd) { + temp = macc_globals->head_pd; + while (temp) { + if (strcmp(buf, temp->field) == 0) { + return; // just ignore duplicates + } + temp = temp->next; + } + } + + struct partial_datacopy *pd = (struct partial_datacopy *)csc2_malloc(sizeof(struct partial_datacopy)); + if (!pd) { + csc2_error("ERROR: OUT OF MEM: %s - ABORTING\n", strerror(errno)); + any_errors++; + return; + } + + pd->field = csc2_strdup(buf); + pd->next = NULL; + if (!macc_globals->head_pd) { + macc_globals->head_pd = pd; /* empty list */ + macc_globals->tail_pd = macc_globals->head_pd; + } else { + macc_globals->tail_pd->next = pd; + macc_globals->tail_pd = macc_globals->tail_pd->next; + } +} + extern int is_valid_datetime(const char *str, const char *tz); void rec_c_add(int typ, int size, char *name, char *cmnt) @@ -2601,6 +2706,12 @@ int dyns_is_idx_datacopy(int index) return dyns_is_idx_flagged(index, DATAKEY); } +/* is key copy-data key (partially)? */ +int dyns_is_idx_partial_datacopy(int index) +{ + return dyns_is_idx_flagged(index, PARTIALDATAKEY); +} + /* is key duplicate? */ int dyns_is_idx_primary(int index) { @@ -2619,6 +2730,24 @@ int dyns_is_idx_uniqnulls(int index) return dyns_is_idx_flagged(index, UNIQNULLS); } +int dyns_get_idx_partial_datacopy(int index, struct partial_datacopy **partial_datacopy) { + int lastix, i; + if (index < 0 || index >= numix()) { + return -1; + } + for (lastix = -1, i = 0; i < numkeys(); i++) { + if (lastix == macc_globals->keyixnum[i]) + continue; + lastix = macc_globals->keyixnum[i]; + if (macc_globals->keyixnum[i] != index) + continue; + *partial_datacopy = macc_globals->keys[i]->pd; + return 0; + } + + return -1; +} + int dyns_get_idx_tag(int index, char *tag, int tlen, char **where) { int lastix = 0, i = 0; diff --git a/csc2/maccparse.y b/csc2/maccparse.y index 2dea6cbd48..2f1592cd5b 100644 --- a/csc2/maccparse.y +++ b/csc2/maccparse.y @@ -458,10 +458,19 @@ multikeyflags: keyflags multikeyflags keyflags: T_DUP { key_setdup(); } | T_RECNUMS { key_setrecnums(); } | T_PRIMARY { key_setprimary(); } + | T_DATAKEY '(' compounddatakey ')' { key_setpartialdatakey(); } | T_DATAKEY { key_setdatakey(); } | T_UNIQNULLS { key_setuniqnulls(); } ; +compounddatakey: datakeypiece + | datakeypiece ',' compounddatakey + ; + +datakeypiece: varname { + datakey_piece_add($1); + }; + compoundkey: keypiece | keypiece '+' compoundkey ; diff --git a/db/comdb2.c b/db/comdb2.c index 4b1d298851..4dab5c6483 100644 --- a/db/comdb2.c +++ b/db/comdb2.c @@ -1011,10 +1011,10 @@ void showdbenv(struct dbenv *dbenv) for (ii = 0; ii < usedb->nix; ii++) { logmsg(LOGMSG_USER, " index %-2d keylen %-3d bytes dupes? %c recnums? %c" - " datacopy? %c collattr? %c uniqnulls %c\n", + " datacopy? %c collattr? %c uniqnulls %c datacopylen %-3d bytes\n", ii, usedb->ix_keylen[ii], (usedb->ix_dupes[ii] ? 'y' : 'n'), (usedb->ix_recnums[ii] ? 'y' : 'n'), (usedb->ix_datacopy[ii] ? 'y' : 'n'), (usedb->ix_collattr[ii] ? 'y' : 'n'), - (usedb->ix_nullsallowed[ii] ? 'y' : 'n')); + (usedb->ix_nullsallowed[ii] ? 'y' : 'n'), (usedb->ix_datacopy[ii] && !usedb->ix_datacopylen[ii] ? usedb->lrl : usedb->ix_datacopylen[ii])); } } for (ii = 0; ii < dbenv->nsiblings; ii++) { diff --git a/db/comdb2.h b/db/comdb2.h index 54652a9133..971b72d2f7 100644 --- a/db/comdb2.h +++ b/db/comdb2.h @@ -613,6 +613,7 @@ typedef struct dbtable { signed char ix_dupes[MAXINDEX]; signed char ix_recnums[MAXINDEX]; signed char ix_datacopy[MAXINDEX]; + int ix_datacopylen[MAXINDEX]; /* datacopy len in bytes (0 if full datacopy) */ signed char ix_collattr[MAXINDEX]; signed char ix_nullsallowed[MAXINDEX]; @@ -2616,10 +2617,10 @@ int process_allow_command(char *line, int lline); int gather_blob_data(struct ireq *iq, const char *tag, blob_status_t *b, const char *to_tag); int gather_blob_data_byname(const char *dbname, const char *tag, - blob_status_t *b); + blob_status_t *b, struct schema *pd); int check_one_blob_consistency(struct ireq *iq, const char *table, const char *tag, blob_status_t *b, void *record, - int blob_index, int cblob); + int blob_index, int cblob, struct schema *pd); int check_blob_consistency(struct ireq *iq, const char *table, const char *tag, blob_status_t *b, const void *record); int check_and_repair_blob_consistency(struct ireq *iq, const char *table, diff --git a/db/constraints.c b/db/constraints.c index 4eb708b0d9..31b9169735 100644 --- a/db/constraints.c +++ b/db/constraints.c @@ -457,7 +457,7 @@ int check_update_constraints(struct ireq *iq, void *trans, ixlen = getkeysize(iq->usedb, ixnum); snprintf(ondisk_tag, MAXTAGLEN, ".ONDISK_IX_%d", ixnum); if (iq->idxDelete) - rc = create_key_from_ireq(iq, ixnum, 1, NULL, NULL, NULL, + rc = create_key_from_ireq(iq, ixnum, 1, NULL, NULL, NULL, NULL, rec_dta, 0 /* not needed */, lkey); else rc = create_key_from_ondisk(iq->usedb, ixnum, rec_dta, lkey); @@ -477,7 +477,7 @@ int check_update_constraints(struct ireq *iq, void *trans, /* this part is for update */ if (newrec_dta != NULL) { if (iq->idxInsert) - rc = create_key_from_ireq(iq, ixnum, 0, NULL, NULL, NULL, + rc = create_key_from_ireq(iq, ixnum, 0, NULL, NULL, NULL, NULL, newrec_dta, 0 /* not needed */, nkey); else @@ -1146,6 +1146,7 @@ int delayed_key_adds(struct ireq *iq, void *trans, int *blkpos, int *ixout, char *od_dta_tail = NULL; int od_tail_len = 0; char mangled_key[MAXKEYLEN]; + char partial_datacopy_tail[MAXRECSZ]; #if DEBUG_REORDER logmsg(LOGMSG_DEBUG, "%s(): entering\n", __func__); @@ -1342,11 +1343,11 @@ int delayed_key_adds(struct ireq *iq, void *trans, int *blkpos, int *ixout, } if (iq->idxInsert) rc = create_key_from_ireq(iq, doidx, 0, &od_dta_tail, - &od_tail_len, mangled_key, od_dta, + &od_tail_len, mangled_key, partial_datacopy_tail, od_dta, ondisk_size, key); else - rc = create_key_from_schema(iq->usedb, NULL, doidx, &od_dta_tail, &od_tail_len, mangled_key, od_dta, - ondisk_size, key, NULL, 0, iq->tzname); + rc = create_key_from_schema(iq->usedb, NULL, doidx, &od_dta_tail, &od_tail_len, mangled_key, partial_datacopy_tail, + od_dta, ondisk_size, key, NULL, 0, iq->tzname); if (rc == -1) { if (iq->debug) reqprintf(iq, "ADDKYCNSTRT CANT FORM INDEX %d", ixnum); @@ -1635,7 +1636,7 @@ int verify_add_constraints(struct ireq *iq, void *trans, int *errout) snprintf(ondisk_tag, MAXTAGLEN, ".ONDISK_IX_%d", lixnum); if (iq->idxInsert) { - rc = create_key_from_ireq(iq, lixnum, 0, NULL, NULL, NULL, + rc = create_key_from_ireq(iq, lixnum, 0, NULL, NULL, NULL, NULL, od_dta, 0 /* not needed */, lkey); } else rc = create_key_from_ondisk(iq->usedb, lixnum, od_dta, lkey); diff --git a/db/fdb_bend_sql.c b/db/fdb_bend_sql.c index 3e809a19fc..b123a15a41 100644 --- a/db/fdb_bend_sql.c +++ b/db/fdb_bend_sql.c @@ -162,8 +162,8 @@ int fdb_svc_alter_schema(struct sqlclntstate *clnt, sqlite3_stmt *stmt, return 0; } - /* if this is a datacopy index, do not do anything */ - if (db->ix_datacopy[ixnum]) { + /* if this is a full datacopy index, do not do anything */ + if (db->ix_datacopy[ixnum] && db->ix_datacopylen[ixnum] == 0) { return 0; } @@ -171,12 +171,12 @@ int fdb_svc_alter_schema(struct sqlclntstate *clnt, sqlite3_stmt *stmt, tblschema = db->schema; ixschema = db->ixschema[ixnum]; - /* already datacopy indexes are ok */ + /* already full datacopy indexes are ok */ if (ixschema->flags & SCHEMA_DATACOPY) { return 0; } - /* we got a non datacopy index, export it as covered index */ + /* we got a non full datacopy index, export it as covered index */ /* get the sql create */ pMem = &upr->aMem[4]; diff --git a/db/glue.c b/db/glue.c index 80fcdc63c0..bb040d741c 100644 --- a/db/glue.c +++ b/db/glue.c @@ -3489,6 +3489,7 @@ int open_auxdbs(struct dbtable *db, int force_create) signed char ixdups[1]; signed char ixrecnum[1]; signed char ixdta[1]; + int ixdtalen[1]; char name[100]; char litename[100]; int bdberr; @@ -3517,6 +3518,7 @@ int open_auxdbs(struct dbtable *db, int force_create) ixdups[0] = 0; ixrecnum[0] = 0; ixdta[0] = 0; + ixdtalen[0] = 0; if (force_create) { if (gbl_meta_lite) @@ -3525,7 +3527,7 @@ int open_auxdbs(struct dbtable *db, int force_create) 0, db->dbenv->bdb_env, &bdberr); else db->meta = bdb_create(name, db->dbenv->basedir, 0, numix, ixlen, - ixdups, ixrecnum, ixdta, NULL, NULL, + ixdups, ixrecnum, ixdta, ixdtalen, NULL, NULL, numdtafiles, db->dbenv->bdb_env, 0, &bdberr); } else { /* see if we have a lite meta table - if so use that. otherwise @@ -3537,7 +3539,7 @@ int open_auxdbs(struct dbtable *db, int force_create) ctrace("bdb_open_more(meta) cannot open lite meta %d\n", bdberr); db->meta = bdb_open_more(name, db->dbenv->basedir, 0, numix, ixlen, - ixdups, ixrecnum, ixdta, NULL, NULL, + ixdups, ixrecnum, ixdta, ixdtalen, NULL, NULL, numdtafiles, db->dbenv->bdb_env, &bdberr); } } @@ -3903,7 +3905,7 @@ int backend_open_tran(struct dbenv *dbenv, tran_type *tran, uint32_t flags) db->handle = bdb_open_more_tran( db->tablename, dbenv->basedir, db->lrl, db->nix, (short *)db->ix_keylen, db->ix_dupes, db->ix_recnums, - db->ix_datacopy, db->ix_collattr, db->ix_nullsallowed, + db->ix_datacopy, db->ix_datacopylen, db->ix_collattr, db->ix_nullsallowed, db->numblobs + 1, /* main record + n blobs */ dbenv->bdb_env, tran, flags, &bdberr); diff --git a/db/indices.c b/db/indices.c index dee285a5fc..2ed5ff008b 100644 --- a/db/indices.c +++ b/db/indices.c @@ -172,6 +172,7 @@ static int check_index(struct ireq *iq, void *trans, int ixnum, blob_buffer_t *b int rc; char key[MAXKEYLEN]; char mangled_key[MAXKEYLEN]; + char partial_datacopy_tail[MAXRECSZ]; char *od_dta_tail = NULL; int od_tail_len; int fndrrn = 0; @@ -192,10 +193,10 @@ static int check_index(struct ireq *iq, void *trans, int ixnum, blob_buffer_t *b if (iq->idxInsert) rc = create_key_from_ireq(iq, ixnum, 0, &od_dta_tail, &od_tail_len, - mangled_key, od_dta, od_len, key); + mangled_key, partial_datacopy_tail, od_dta, od_len, key); else { - rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_dta_tail, &od_tail_len, mangled_key, od_dta, od_len, - key, blobs, maxblobs, iq->tzname); + rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_dta_tail, &od_tail_len, mangled_key, partial_datacopy_tail, + od_dta, od_len, key, blobs, maxblobs, iq->tzname); } if (rc == -1) { if (iq->debug) @@ -326,6 +327,7 @@ int add_record_indices(struct ireq *iq, void *trans, blob_buffer_t *blobs, for (int ixnum = 0; ixnum < iq->usedb->nix; ixnum++) { char *key = ditk.ixkey; // key points to chararray regardless reordering char mangled_key[MAXKEYLEN]; + char partial_datacopy_tail[MAXRECSZ]; if (gbl_use_plan && iq->usedb->plan && iq->usedb->plan->ix_plan[ixnum] != -1) @@ -351,10 +353,10 @@ int add_record_indices(struct ireq *iq, void *trans, blob_buffer_t *blobs, if (iq->idxInsert) rc = create_key_from_ireq(iq, ixnum, 0, &od_dta_tail, &od_tail_len, - mangled_key, od_dta, od_len, key); + mangled_key, partial_datacopy_tail, od_dta, od_len, key); else { - rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_dta_tail, &od_tail_len, mangled_key, od_dta, od_len, - key, blobs, maxblobs, iq->tzname); + rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_dta_tail, &od_tail_len, mangled_key, partial_datacopy_tail, + od_dta, od_len, key, blobs, maxblobs, iq->tzname); } if (rc == -1) { if (iq->debug) @@ -549,6 +551,8 @@ int upd_record_indices(struct ireq *iq, void *trans, int *opfailcode, char *newkey = ditk.ixkey; char mangled_oldkey[MAXKEYLEN]; char mangled_newkey[MAXKEYLEN]; + char partial_datacopy_oldtail[MAXRECSZ]; + char partial_datacopy_newtail[MAXRECSZ]; /* index doesnt change */ if (gbl_partial_indexes && iq->usedb->ix_partial && @@ -567,10 +571,10 @@ int upd_record_indices(struct ireq *iq, void *trans, int *opfailcode, if (!gbl_partial_indexes || !iq->usedb->ix_partial || (del_keys & (1ULL << ixnum))) rc = create_key_from_ireq(iq, ixnum, 1, &od_olddta_tail, - &od_oldtail_len, mangled_oldkey, + &od_oldtail_len, mangled_oldkey, partial_datacopy_oldtail, old_dta, od_len, oldkey); } else - rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_olddta_tail, &od_oldtail_len, mangled_oldkey, + rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_olddta_tail, &od_oldtail_len, mangled_oldkey, partial_datacopy_oldtail, old_dta, od_len, oldkey, del_idx_blobs, MAXBLOBS, NULL); if (rc < 0) { if (iq->debug) @@ -588,11 +592,11 @@ int upd_record_indices(struct ireq *iq, void *trans, int *opfailcode, if (!gbl_partial_indexes || !iq->usedb->ix_partial || (ins_keys & (1ULL << ixnum))) rc = create_key_from_ireq(iq, ixnum, 0, &od_dta_tail, - &od_tail_len, mangled_newkey, od_dta, + &od_tail_len, mangled_newkey, partial_datacopy_newtail, od_dta, od_len, newkey); } else /* form the new key from "od_dta" into "newkey" */ - rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_dta_tail, &od_tail_len, mangled_newkey, od_dta, - od_len, newkey, add_idx_blobs, MAXBLOBS, NULL); + rc = create_key_from_schema(iq->usedb, NULL, ixnum, &od_dta_tail, &od_tail_len, mangled_newkey, partial_datacopy_newtail, + od_dta, od_len, newkey, add_idx_blobs, MAXBLOBS, NULL); if (rc < 0) { if (iq->debug) reqprintf(iq, "CAN'T FORM NEW KEY IX %d", ixnum); @@ -960,6 +964,7 @@ int upd_new_record_add2indices(struct ireq *iq, void *trans, for (int ixnum = 0; ixnum < iq->usedb->nix; ixnum++) { char key[MAXKEYLEN]; char mangled_key[MAXKEYLEN]; + char partial_datacopy_tail[MAXRECSZ]; char *od_dta_tail = NULL; int od_tail_len = 0; @@ -977,11 +982,11 @@ int upd_new_record_add2indices(struct ireq *iq, void *trans, if (iq->idxInsert) rc = create_key_from_ireq(iq, ixnum, 0, &od_dta_tail, &od_tail_len, - mangled_key, (char *)new_dta, nd_len, key); + mangled_key, partial_datacopy_tail, (char *)new_dta, nd_len, key); else { rc = create_key_from_schema( iq->usedb, use_new_tag ? NULL : find_tag_schema(iq->usedb->tablename, ".ONDISK"), ixnum, &od_dta_tail, - &od_tail_len, mangled_key, new_dta, nd_len, key, blobs, MAXBLOBS, NULL); + &od_tail_len, mangled_key, partial_datacopy_tail, new_dta, nd_len, key, blobs, MAXBLOBS, NULL); } if (rc) { diff --git a/db/macc_glue.c b/db/macc_glue.c index be8a64f222..4c080891e2 100644 --- a/db/macc_glue.c +++ b/db/macc_glue.c @@ -200,7 +200,7 @@ static dbtable *newdb_from_schema(struct dbenv *env, char *tblname, int dbnum, return NULL; } - tbl->ix_datacopy[ii] = dyns_is_idx_datacopy(ii); + tbl->ix_datacopy[ii] = dyns_is_idx_datacopy(ii) | dyns_is_idx_partial_datacopy(ii); if (tbl->ix_datacopy[ii] < 0) { logmsg(LOGMSG_ERROR, "cant find index %d datacopy in csc schema %s\n", ii, @@ -292,6 +292,8 @@ static int create_key_schema(dbtable *db, struct schema *schema, int alt, int ascdesc; char *dbname = db->tablename; struct schema *s; + struct schema *p; + struct partial_datacopy *pd; /* keys not reqd for ver temp table; just ondisk tag */ if (strncasecmp(dbname, gbl_ver_temp_table, strlen(gbl_ver_temp_table)) == @@ -311,6 +313,8 @@ static int create_key_schema(dbtable *db, struct schema *schema, int alt, s->flags = SCHEMA_INDEX; + db->ix_datacopylen[ix] = 0; + if (dyns_is_idx_dup(ix)) s->flags |= SCHEMA_DUP; @@ -323,6 +327,68 @@ static int create_key_schema(dbtable *db, struct schema *schema, int alt, if (dyns_is_idx_uniqnulls(ix)) s->flags |= SCHEMA_UNIQNULLS; + if (dyns_is_idx_partial_datacopy(ix)) { + s->flags |= SCHEMA_PARTIALDATACOPY; + + rc = dyns_get_idx_partial_datacopy(ix, &pd); + if (rc == 0 && pd) { + p = s->partial_datacopy = calloc(1, sizeof(struct schema)); + + // find number of members + int numMembers = 0; + struct partial_datacopy *temp = pd; + while (temp) { + temp = temp->next; + numMembers++; + } + + p->tag = NULL; + p->datacopy = NULL; + p->csctag = NULL; + p->sqlitetag = NULL; + p->partial_datacopy = NULL; + p->flags = SCHEMA_PARTIALDATACOPY_ACTUAL; + + p->nmembers = numMembers; + p->member = calloc(p->nmembers, sizeof(struct field)); + + temp = pd; + piece = 0; + offset = 0; + while (temp) { + m = &p->member[piece]; + m->idx = find_field_idx(dbname, schema->tag, temp->field); + if (m->idx == -1) { + rc = -ix - 1; + goto errout; + } + + m->isExpr = 0; + m->in_default = NULL; + m->out_default = NULL; + m->name = strdup(temp->field); + m->offset = offset; + m->flags = schema->member[m->idx].flags; + m->blob_index = schema->member[m->idx].blob_index; + m->type = schema->member[m->idx].type; + m->len = schema->member[m->idx].len; + offset += m->len; + memcpy(&m->convopts, &schema->member[m->idx].convopts, sizeof(struct field_conv_opts)); + + temp = temp->next; + piece++; + } + + db->ix_datacopylen[ix] = offset; + + } else { + errstat_set_rcstrf(err, -1, "cannot form partial datacopy for index %d.", ix); + goto errout; + } + } else { + s->partial_datacopy = NULL; + } + s->nix = 0; s->ix = NULL; s->ixnum = ix; diff --git a/db/osqlshadtbl.c b/db/osqlshadtbl.c index a1c4792986..2d4c429f31 100644 --- a/db/osqlshadtbl.c +++ b/db/osqlshadtbl.c @@ -2208,8 +2208,18 @@ static int insert_record_indexes(BtCursor *pCur, struct sql_thread *thd, } if (pCur->db->ix_datacopy[ix]) { - datacopy = pCur->ondisk_buf; - datacopylen = getdatsize(pCur->db); + if (pCur->db->ix_datacopylen[ix] > 0) { // partial datacopy + datacopy = alloca(pCur->db->ix_datacopylen[ix]); + rc = stag_to_stag_buf_schemas(get_schema(pCur->db, -1), get_schema(pCur->db, ix)->partial_datacopy, pCur->ondisk_buf, datacopy, pCur->db->tablename); + if (rc == -1) { + logmsg(LOGMSG_ERROR, "insert_record:partial datacopy conversion ix %d\n", ix); + return SQLITE_INTERNAL; + } + datacopylen = pCur->db->ix_datacopylen[ix]; + } else { + datacopy = pCur->ondisk_buf; + datacopylen = getdatsize(pCur->db); + } } else if (pCur->db->ix_collattr[ix]) { datacopy = alloca(4 * pCur->db->ix_collattr[ix]); diff --git a/db/sqlglue.c b/db/sqlglue.c index 643712eb01..86795a5d1e 100644 --- a/db/sqlglue.c +++ b/db/sqlglue.c @@ -1459,9 +1459,24 @@ void form_new_style_name(char *namebuf, int len, struct schema *schema, unsigned int crc; SNPRINTF(buf, sizeof(buf), current, "%s", dbname) - if (schema->flags & SCHEMA_DATACOPY) + if (schema->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY)) { SNPRINTF(buf, sizeof(buf), current, "%s", "DATACOPY") + if (schema->flags & SCHEMA_PARTIALDATACOPY) { + struct schema *partial_datacopy = schema->partial_datacopy; + + SNPRINTF(buf, sizeof(buf), current, "%s", "(") + for (fieldctr = 0; fieldctr < partial_datacopy->nmembers; fieldctr++) { + if (fieldctr > 0) { + SNPRINTF(buf, sizeof(buf), current, "%s", ", ") + } + + SNPRINTF(buf, sizeof(buf), current, "%s", partial_datacopy->member[fieldctr].name) + } + SNPRINTF(buf, sizeof(buf), current, "%s", ")") + } + } + if (schema->flags & SCHEMA_DUP) SNPRINTF(buf, sizeof(buf), current, "%s", "DUP") @@ -1725,8 +1740,10 @@ int create_datacopy_array(struct dbtable *tbl) return -1; } - if (!(schema->flags & SCHEMA_DATACOPY)) { + if (!(schema->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY))) { continue; + } else if (schema->flags & SCHEMA_PARTIALDATACOPY) { + ondisk = schema->partial_datacopy; } int datacopy_pos = 0; @@ -1895,8 +1912,11 @@ static int create_sqlmaster_record(struct dbtable *tbl, void *tran) strbuf_append(sql, " DESC"); } - if (schema->flags & SCHEMA_DATACOPY) { + if (schema->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY)) { struct schema *ondisk = tbl->schema; + if (schema->flags & SCHEMA_PARTIALDATACOPY) { + ondisk = schema->partial_datacopy; + } int first = 1; /* Add all fields from ONDISK to index */ for (int ondisk_i = 0; ondisk_i < ondisk->nmembers; ++ondisk_i) { @@ -6591,10 +6611,15 @@ static int fetch_blob_into_sqlite_mem(BtCursor *pCur, struct schema *sc, int bdberr; int nretries = 0; struct sql_thread *thd = pCur->thd; + struct schema *pd = NULL; + + if (sc->flags & SCHEMA_PARTIALDATACOPY_ACTUAL) { + pd = sc; + } if (!pCur->have_blob_descriptor) { gather_blob_data_byname(pCur->db->tablename, ".ONDISK", - &pCur->blob_descriptor); + &pCur->blob_descriptor, pd); pCur->have_blob_descriptor = 1; } @@ -6651,7 +6676,7 @@ static int fetch_blob_into_sqlite_mem(BtCursor *pCur, struct schema *sc, iq.usedb = pCur->db; if (check_one_blob_consistency(&iq, iq.usedb->tablename, ".ONDISK", &blobs, - dta, f->blob_index, 0)) { + dta, f->blob_index, 0, pd)) { free_blob_status_data(&blobs); nretries++; if (nretries >= gbl_maxblobretries) { @@ -7146,14 +7171,18 @@ int get_data(BtCursor *pCur, struct schema *sc, uint8_t *in, int fnum, Mem *m, int get_datacopy(BtCursor *pCur, int fnum, Mem *m) { uint8_t *in; + struct schema *s; + s = pCur->db->schema; in = pCur->bdbcur->datacopy(pCur->bdbcur); - if (!is_genid_synthetic(pCur->genid)) { + if (s->ix[pCur->ixnum]->flags & SCHEMA_PARTIALDATACOPY) { + s = s->ix[pCur->ixnum]->partial_datacopy; + } else if (!is_genid_synthetic(pCur->genid)) { uint8_t ver = pCur->bdbcur->ver(pCur->bdbcur); vtag_to_ondisk_vermap(pCur->db, in, NULL, ver); } - return get_data(pCur, pCur->db->schema, in, fnum, m, 0, pCur->clnt->tzname); + return get_data(pCur, s, in, fnum, m, 0, pCur->clnt->tzname); } static int @@ -8064,7 +8093,7 @@ sqlite3BtreeCursor_cursor(Btree *pBt, /* The btree */ /* check one time if we have blobs when we open the cursor, * so we dont need to run this code for every row if we dont even * have them */ - rc = gather_blob_data_byname(cur->db->tablename, ".ONDISK", &cur->blobs); + rc = gather_blob_data_byname(cur->db->tablename, ".ONDISK", &cur->blobs, NULL); if (rc) { logmsg(LOGMSG_ERROR, "sqlite3BtreeCursor: gather_blob_data error rc=%d\n", rc); return SQLITE_INTERNAL; diff --git a/db/tag.c b/db/tag.c index fe395a8eba..2cba8d139e 100644 --- a/db/tag.c +++ b/db/tag.c @@ -3144,6 +3144,11 @@ void free_db_record(struct dbrecord *db) free(db); } +int stag_to_stag_buf_schemas(struct schema *fromsch, struct schema *tosch, const char *inbuf, char *outbuf, const char *tzname) +{ + return _stag_to_stag_buf_flags_blobs(fromsch, tosch, inbuf, outbuf, 0, NULL, NULL, NULL, 0, tzname); +} + int stag_to_stag_buf_blobs(const char *table, const char *fromtag, const char *inbuf, const char *totag, char *outbuf, struct convert_failure *reason, blob_buffer_t *blobs, @@ -4323,8 +4328,8 @@ int cmp_index_int(struct schema *oldix, struct schema *newix, char *descr, int oldattr, newattr; /* First compare attributes */ - oldattr = oldix->flags & (SCHEMA_DUP | SCHEMA_RECNUM | SCHEMA_DATACOPY | SCHEMA_UNIQNULLS); - newattr = newix->flags & (SCHEMA_DUP | SCHEMA_RECNUM | SCHEMA_DATACOPY | SCHEMA_UNIQNULLS); + oldattr = oldix->flags & (SCHEMA_DUP | SCHEMA_RECNUM | SCHEMA_DATACOPY | SCHEMA_UNIQNULLS | SCHEMA_PARTIALDATACOPY); + newattr = newix->flags & (SCHEMA_DUP | SCHEMA_RECNUM | SCHEMA_DATACOPY | SCHEMA_UNIQNULLS | SCHEMA_PARTIALDATACOPY); if (oldattr != newattr) { if (descr) snprintf(descr, descrlen, "properties have changed"); @@ -4362,6 +4367,21 @@ int cmp_index_int(struct schema *oldix, struct schema *newix, char *descr, return 1; } } + + if (oldix->flags & newix->flags & SCHEMA_PARTIALDATACOPY) { + struct schema *oldpd = oldix->partial_datacopy; + struct schema *newpd = newix->partial_datacopy; + char *descr_helper = descr ? calloc(descrlen, sizeof(char)) : descr; + if (cmp_index_int(oldpd, newpd, descr_helper, descrlen)) { + if (descr) { + snprintf(descr, descrlen, "%s in partial datacopy", descr_helper); + free(descr_helper); + } + return 1; + } + if (descr) + free(descr_helper); + } } return 0; } @@ -5310,6 +5330,14 @@ struct schema *clone_schema(struct schema *from) sc->datacopy = malloc(from->nmembers * sizeof(int)); memcpy(sc->datacopy, from->datacopy, from->nmembers * sizeof(int)); } + if (from->partial_datacopy) { + sc->partial_datacopy = calloc(1, sizeof(struct schema)); + sc->partial_datacopy->nmembers = from->partial_datacopy->nmembers; + sc->partial_datacopy->member = calloc(sc->partial_datacopy->nmembers, sizeof(struct field)); + for (i = 0; i < sc->partial_datacopy->nmembers; i++) { + sc->partial_datacopy->member[i].name = strdup(from->partial_datacopy->member[i].name); + } + } return sc; } @@ -6003,6 +6031,10 @@ void freeschema_internals(struct schema *schema) free(schema->sqlitetag); schema->sqlitetag = NULL; } + if (schema->partial_datacopy) { + freeschema(schema->partial_datacopy); + schema->partial_datacopy = NULL; + } } void freeschema(struct schema *schema) @@ -6233,7 +6265,7 @@ static int load_new_ondisk(dbtable *db, tran_type *tran) newdb->handle = bdb_open_more_tran( db->tablename, thedb->basedir, newdb->lrl, newdb->nix, (short *)newdb->ix_keylen, newdb->ix_dupes, newdb->ix_recnums, - newdb->ix_datacopy, newdb->ix_collattr, newdb->ix_nullsallowed, + newdb->ix_datacopy, newdb->ix_datacopylen, newdb->ix_collattr, newdb->ix_nullsallowed, newdb->numblobs + 1, thedb->bdb_env, arg_tran, 0, &bdberr); if (bdberr != 0 || newdb->handle == NULL) { @@ -6616,8 +6648,8 @@ int extract_decimal_quantum(const dbtable *db, int ix, char *inbuf, } int create_key_from_schema(const struct dbtable *db, struct schema *schema, int ixnum, char **tail, int *taillen, - char *mangled_key, const char *inbuf, int inbuflen, char *outbuf, blob_buffer_t *inblobs, - int maxblobs, const char *tzname) + char *mangled_key, char *partial_datacopy_tail, const char *inbuf, int inbuflen, + char *outbuf, blob_buffer_t *inblobs, int maxblobs, const char *tzname) { int rc = 0; struct schema *fromsch, *tosch; @@ -6669,8 +6701,18 @@ int create_key_from_schema(const struct dbtable *db, struct schema *schema, int fromtag, totag); abort(); } - *tail = (char *)inbuf; - *taillen = inbuflen; + if (partial_datacopy_tail && (tosch->flags & SCHEMA_PARTIALDATACOPY)) { + rc = _stag_to_stag_buf_flags_blobs(fromsch, tosch->partial_datacopy, inbuf, partial_datacopy_tail, 0 /*flags*/, NULL, inblobs, NULL /*outblobs*/, + maxblobs, tzname); + if (rc) + return rc; + + *tail = (char *)partial_datacopy_tail; + *taillen = get_size_of_schema(tosch->partial_datacopy); + } else { + *tail = (char *)inbuf; + *taillen = inbuflen; + } } } else if (db->ix_collattr[ixnum]) { assert(db->ix_datacopy[ixnum] == 0); @@ -6700,18 +6742,18 @@ int create_key_from_schema(const struct dbtable *db, struct schema *schema, int int create_key_from_ondisk(const struct dbtable *db, int ixnum, const char *inbuf, char *outbuf) { - return create_key_from_schema(db, NULL, ixnum, NULL, NULL, NULL, inbuf, 0, outbuf, NULL, 0, NULL); + return create_key_from_schema(db, NULL, ixnum, NULL, NULL, NULL, NULL, inbuf, 0, outbuf, NULL, 0, NULL); } int create_key_from_schema_simple(const struct dbtable *db, struct schema *schema, int ixnum, const char *inbuf, char *outbuf, blob_buffer_t *inblobs, int maxblobs) { - return create_key_from_schema(db, schema, ixnum, NULL, NULL, NULL, inbuf, 0, outbuf, inblobs, maxblobs, NULL); + return create_key_from_schema(db, schema, ixnum, NULL, NULL, NULL, NULL, inbuf, 0, outbuf, inblobs, maxblobs, NULL); } int create_key_from_ireq(struct ireq *iq, int ixnum, int isDelete, char **tail, - int *taillen, char *mangled_key, const char *inbuf, - int inbuflen, char *outbuf) + int *taillen, char *mangled_key, char *partial_datacopy_tail, + const char *inbuf, int inbuflen, char *outbuf) { int rc = 0; dbtable *db = iq->usedb; @@ -6737,8 +6779,20 @@ int create_key_from_ireq(struct ireq *iq, int ixnum, int isDelete, char **tail, } rc = -1; /* callers like -1 */ } else if (tail) { - *tail = (char *)inbuf; - *taillen = inbuflen; + struct schema *fromsch = get_schema(db, -1); + struct schema *tosch = get_schema(db, ixnum); + if (partial_datacopy_tail && (tosch->flags & SCHEMA_PARTIALDATACOPY)) { + rc = _stag_to_stag_buf_flags_blobs(fromsch, tosch->partial_datacopy, inbuf, partial_datacopy_tail, 0 /*flags*/, NULL, NULL /*inblobs*/, NULL /*outblobs*/, + 0 /*maxblobs*/, iq->tzname); + if (rc) + return rc; + + *tail = (char *)partial_datacopy_tail; + *taillen = get_size_of_schema(tosch->partial_datacopy); + } else { + *tail = (char *)inbuf; + *taillen = inbuflen; + } } } else if (db->ix_collattr[ixnum]) { assert(db->ix_datacopy[ixnum] == 0); diff --git a/db/tag.h b/db/tag.h index fb2686df00..d0a0ddaa51 100644 --- a/db/tag.h +++ b/db/tag.h @@ -65,6 +65,7 @@ struct schema { int flags; int nix; struct schema **ix; + struct schema *partial_datacopy; int ixnum; /* for indices, number of index in struct dbtable */ int ix_blob; /* set to 1 if blobs are involved in indexes */ int recsize; /* for tables, gives the length of the record structure */ @@ -102,7 +103,9 @@ enum { , SCHEMA_DYNAMIC = 16, SCHEMA_DATACOPY = 32, /* datacopy flag set on index */ - SCHEMA_UNIQNULLS = 64 /* treat all NULL values as UNIQUE */ + SCHEMA_UNIQNULLS = 64, /* treat all NULL values as UNIQUE */ + SCHEMA_PARTIALDATACOPY = 128, /* partial datacopy flag set on index */ + SCHEMA_PARTIALDATACOPY_ACTUAL = 256 /* schema that contains partial datacopy fields referenced by partial datacopy index */ }; /* sql_record_member.flags */ @@ -227,6 +230,8 @@ int stag_to_ctag_buf_blobs_tz(const char *table, const char *stag, blob_buffer_t *inblobs, blob_buffer_t *outblobs, int maxblobs, const char *tzname); +int stag_to_stag_buf_schemas(struct schema *fromsch, struct schema *tosch, + const char *inbuf, char *outbuf, const char *tzname); int stag_to_stag_buf_blobs(const char *table, const char *fromtag, const char *inbuf, const char *totag, char *outbuf, struct convert_failure *reason, blob_buffer_t *blobs, @@ -409,12 +414,12 @@ int create_key_from_schema_simple(const struct dbtable *db, struct schema *schem char *outbuf, blob_buffer_t *inblobs, int maxblobs); int create_key_from_schema(const struct dbtable *db, struct schema *schema, int ixnum, char **tail, int *taillen, - char *mangled_key, const char *inbuf, int inbuflen, char *outbuf, blob_buffer_t *inblobs, - int maxblobs, const char *tzname); + char *mangled_key, char *partial_datacopy_tail, const char *inbuf, int inbuflen, + char *outbuf, blob_buffer_t *inblobs, int maxblobs, const char *tzname); int create_key_from_ireq(struct ireq *iq, int ixnum, int isDelete, char **tail, - int *taillen, char *mangled_key, const char *inbuf, - int inbuflen, char *outbuf); + int *taillen, char *mangled_key, char *partial_datacopy_tail, + const char *inbuf, int inbuflen, char *outbuf); char* typestr(int type, int len); diff --git a/db/toblob.c b/db/toblob.c index 6f1848a635..9f457cca83 100644 --- a/db/toblob.c +++ b/db/toblob.c @@ -828,8 +828,24 @@ int gather_blob_data(struct ireq *iq, const char *tag, blob_status_t *b, return 0; } +/* helper function for gather_blob_data_byname + * to convert index of blob in full table schema + * to index in partial datacopy schema + */ +static int convert_idx_partial_datacopy(int blob_idx, struct schema *pd) { + for (int piece = 0; piece < pd->nmembers; piece++) { + if (pd->member[piece].idx == blob_idx) { + return piece; + } + } + + return -1; +} + +/* pd == NULL if not using partial datacopy fields + */ int gather_blob_data_byname(const char *dbname, const char *tag, - blob_status_t *b) + blob_status_t *b, struct schema *pd) { int cblob; memset(b, 0, sizeof(*b)); @@ -838,6 +854,9 @@ int gather_blob_data_byname(const char *dbname, const char *tag, int diskblob, blob_idx; diskblob = blob_no_to_blob_no(dbname, tag, cblob, ".ONDISK"); blob_idx = get_schema_blob_field_idx(dbname, tag, cblob); + if (pd) { // convert to index in partial datacopy schema + blob_idx = convert_idx_partial_datacopy(blob_idx, pd); + } if (diskblob < 0 || blob_idx < 0) { logmsg(LOGMSG_ERROR, "BLOB LOOKUP ERR SORTING CLIENT BLOB %d DISKBLOB " "%d SCHEMA IDX %d", @@ -1086,12 +1105,16 @@ static int check_blob_consistency_int(struct ireq *iq, const char *table, /* do what we do in check_blob_consistency_int(iq, table, tag, b, record, 0); * but for one blob only. + * pd == NULL if not using partial datacopy fields */ int check_one_blob_consistency(struct ireq *iq, const char *table, const char *tag, blob_status_t *b, void *record, - int blob_index, int cblob) + int blob_index, int cblob, struct schema *pd) { - struct schema *schema = find_tag_schema(table, tag); + struct schema *schema = pd; + if (!schema) { + schema = find_tag_schema(table, tag); + } int isondisk = is_tag_ondisk_sc(schema); b->total_length = 0; diff --git a/db/verify.c b/db/verify.c index 41b016992e..bda632fdab 100644 --- a/db/verify.c +++ b/db/verify.c @@ -252,6 +252,11 @@ static int verify_formkey_callback(const dbtable *tbl, void *dta, return create_key_from_schema_simple(tbl, NULL, ix, dta, keyout, blob_parm, MAXBLOBS); } +static int convert_to_partial_datacopy(const struct dbtable *tbl, const int pd_ix, const void *inbuf, void *outbuf) +{ + return stag_to_stag_buf_schemas(tbl->schema, tbl->schema->ix[pd_ix]->partial_datacopy, inbuf, outbuf, tbl->tablename); +} + static int verify_add_blob_buffer_callback(void *parm, void *dta, int dtasz, int blobno) { @@ -325,6 +330,7 @@ int verify_table(const char *table, int progress_report_seconds, pthread_once(&once, init_verify_thdpool); verify_common_t par = { .tablename = table, + .partial_datacopy_callback = convert_to_partial_datacopy, .formkey_callback = verify_formkey_callback, .get_blob_sizes_callback = verify_blobsizes_callback, .vtag_callback = (int (*)(void *, void *, int *, uint8_t))vtag_to_ondisk_vermap, diff --git a/docs/images/key-section.gif b/docs/images/key-section.gif index 5e6d6636bd9c0b1ed4b7b75c73c6326f992a3357..5b0c26a8f9f6712a85136f8bcdc286dae7189471 100644 GIT binary patch literal 15030 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 diff --git a/docs/pages/programming/system_tables.md b/docs/pages/programming/system_tables.md index 43eb5bcfc5..5db838661d 100644 --- a/docs/pages/programming/system_tables.md +++ b/docs/pages/programming/system_tables.md @@ -195,7 +195,7 @@ Describes all the components of the keys. Describes all of the keys in the database. comdb2_keys(tablename, keyname, keynumber, isunique, isdatacopy, - isrecnum, condition) + isrecnum, condition, ispartialdatacopy) * `tablename` - Name of the table * `keyname` - Name of the key @@ -204,6 +204,7 @@ Describes all of the keys in the database. * `isrecnum` - `Y` if this key has recnums * `condition` - Where condition for this index * `uniqnulls` - `Y` if this key treats NULL values as unique +* `ispartialdatacopy` - `Y` if some subset of the data is inlined with this key ## comdb2_keywords @@ -292,6 +293,16 @@ Lists all opcode handlers available in Comdb2. * `opcode` - Number assigned to the opcode handler * `name` - Name of the opcode handler +## comdb2_partial_datacopies + +Lists all of the partial datacopy columns for each relevant key in the database. + + comdb2_partial_datacopies(tablename, keyname, columnname) + +* `tablename` - Name of the table with partial datacopy +* `keyname` - Name of the key with partial datacopy +* `columnname` - Name of the column included in partial datacopy for `keyname` + ## comdb2_plugins Lists all plugins currently available in Comdb2. diff --git a/docs/pages/programming/table_schema.md b/docs/pages/programming/table_schema.md index 7ec51e3970..e054f68b9a 100644 --- a/docs/pages/programming/table_schema.md +++ b/docs/pages/programming/table_schema.md @@ -293,6 +293,10 @@ the data record in the btree used for the index. This copy is maintained transp This allows for large performance gains when reading sequential records from on a key. The trade-off is the use of more disk space. +To only copy a subset of the columns (partial datacopy), follow the ```datacopy``` keyword by a comma-separated list of columns +closed by parentheses to include in the datacopy. Note that currently partial datacopies cannot be used at all +in tables that contain decimal fields. + ### Unique NULL Keys. If the key definition is preceded by the ```uniqnulls``` keyword, then the backing index will treat NULL values as unique. diff --git a/docs/src/sqlitegen/bubble-generator-data.tcl b/docs/src/sqlitegen/bubble-generator-data.tcl index 416e91d6a9..d71b8fb357 100644 --- a/docs/src/sqlitegen/bubble-generator-data.tcl +++ b/docs/src/sqlitegen/bubble-generator-data.tcl @@ -589,7 +589,16 @@ stack {opt dup} {opt uniqnulls} } - {opt datacopy} + {opt datacopy + {opt + ( + {loop + column-name + , + } + ) + } + } {line /string-literal = } } {stack diff --git a/schemachange/sc_add_table.c b/schemachange/sc_add_table.c index 1e2b504612..f29686a1eb 100644 --- a/schemachange/sc_add_table.c +++ b/schemachange/sc_add_table.c @@ -59,7 +59,7 @@ static inline int get_db_handle(struct dbtable *newdb, void *trans) newdb->handle = bdb_create_tran( newdb->tablename, thedb->basedir, newdb->lrl, newdb->nix, (short *)newdb->ix_keylen, newdb->ix_dupes, newdb->ix_recnums, - newdb->ix_datacopy, newdb->ix_collattr, newdb->ix_nullsallowed, + newdb->ix_datacopy, newdb->ix_datacopylen, newdb->ix_collattr, newdb->ix_nullsallowed, newdb->numblobs + 1, thedb->bdb_env, 0, &bdberr, trans); open_auxdbs(newdb, 1); } else { @@ -67,7 +67,7 @@ static inline int get_db_handle(struct dbtable *newdb, void *trans) newdb->handle = bdb_open_more_tran( newdb->tablename, thedb->basedir, newdb->lrl, newdb->nix, (short *)newdb->ix_keylen, newdb->ix_dupes, newdb->ix_recnums, - newdb->ix_datacopy, newdb->ix_collattr, newdb->ix_nullsallowed, + newdb->ix_datacopy, newdb->ix_datacopylen, newdb->ix_collattr, newdb->ix_nullsallowed, newdb->numblobs + 1, thedb->bdb_env, trans, 0, &bdberr); open_auxdbs(newdb, 0); } diff --git a/schemachange/sc_logic.c b/schemachange/sc_logic.c index b700e091d0..c8a7c7781f 100644 --- a/schemachange/sc_logic.c +++ b/schemachange/sc_logic.c @@ -1220,7 +1220,7 @@ int open_temp_db_resume(struct dbtable *db, char *prefix, int resume, int temp, db->handle = bdb_open_more( tmpname, db->dbenv->basedir, db->lrl, db->nix, (short *)db->ix_keylen, db->ix_dupes, db->ix_recnums, - db->ix_datacopy, db->ix_collattr, db->ix_nullsallowed, + db->ix_datacopy, db->ix_datacopylen, db->ix_collattr, db->ix_nullsallowed, db->numblobs + 1, /* one main record + the blobs blobs */ db->dbenv->bdb_env, &bdberr); @@ -1243,7 +1243,7 @@ int open_temp_db_resume(struct dbtable *db, char *prefix, int resume, int temp, db->handle = bdb_create_tran( tmpname, db->dbenv->basedir, db->lrl, db->nix, (short *)db->ix_keylen, db->ix_dupes, db->ix_recnums, - db->ix_datacopy, db->ix_collattr, db->ix_nullsallowed, + db->ix_datacopy, db->ix_datacopylen, db->ix_collattr, db->ix_nullsallowed, db->numblobs + 1, /* one main record + the blobs blobs */ db->dbenv->bdb_env, temp, &bdberr, tran); if (db->handle == NULL) { diff --git a/schemachange/sc_schema.c b/schemachange/sc_schema.c index 5bfd1386a7..5a5a79449c 100644 --- a/schemachange/sc_schema.c +++ b/schemachange/sc_schema.c @@ -897,7 +897,7 @@ int create_schema_change_plan(struct schema_change_type *s, struct dbtable *oldd /* If the new index has datacopy and there are ondisk changes then * the index must be rebuilt. */ - if ((newixs->flags & SCHEMA_DATACOPY) && plan->dta_plan == -1) { + if ((newixs->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY)) && plan->dta_plan == -1) { plan->ix_plan[ixn] = -1; } else { /* Try to find an unused index in the old file which exactly matches @@ -915,7 +915,7 @@ int create_schema_change_plan(struct schema_change_type *s, struct dbtable *oldd } if (newdb->odh && /* table has odh */ - (newixs->flags & SCHEMA_DATACOPY) && /* index had datacopy */ + (newixs->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY)) && /* index had datacopy */ !datacopy_odh) /* index did not have odh in datacopy */ { plan->ix_plan[ixn] = -1; @@ -928,7 +928,7 @@ int create_schema_change_plan(struct schema_change_type *s, struct dbtable *oldd if (plan->ix_plan[ixn] == -1) plan->plan_convert = 1; char *str_datacopy; - if (newixs->flags & SCHEMA_DATACOPY) { + if (newixs->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY)) { if (olddb->odh) { if (newdb->odh) { if (datacopy_odh) { @@ -1265,7 +1265,7 @@ int check_sc_headroom(struct schema_change_type *s, struct dbtable *olddb, /* If an index has a blob field or is datacopy, the size will rise based on the blob size or data size. So still use the old way here. */ - if (!ix->ix_blob && !(ix->flags & SCHEMA_DATACOPY)) + if (!ix->ix_blob && !(ix->flags & (SCHEMA_DATACOPY | SCHEMA_PARTIALDATACOPY))) pct += get_size_of_schema(ix) / (double)lrl; } } diff --git a/schemachange/sc_struct.c b/schemachange/sc_struct.c index 897d6eff06..bc3aae3ef9 100644 --- a/schemachange/sc_struct.c +++ b/schemachange/sc_struct.c @@ -930,7 +930,7 @@ static int reload_csc2_schema(struct dbtable *db, tran_type *tran, newdb->handle = bdb_open_more_tran( table, thedb->basedir, newdb->lrl, newdb->nix, (short *)newdb->ix_keylen, newdb->ix_dupes, newdb->ix_recnums, - newdb->ix_datacopy, newdb->ix_collattr, newdb->ix_nullsallowed, + newdb->ix_datacopy, newdb->ix_datacopylen, newdb->ix_collattr, newdb->ix_nullsallowed, newdb->numblobs + 1, thedb->bdb_env, tran, 0, &bdberr); logmsg(LOGMSG_DEBUG, "reload_schema handle %p bdberr %d\n", newdb->handle, bdberr); @@ -1019,7 +1019,7 @@ int reload_schema(char *table, const char *csc2, tran_type *tran) /* faffing with schema required. schema can change in fastinit */ new_bdb_handle = bdb_open_more_tran( table, thedb->basedir, db->lrl, db->nix, (short *)db->ix_keylen, - db->ix_dupes, db->ix_recnums, db->ix_datacopy, db->ix_collattr, + db->ix_dupes, db->ix_recnums, db->ix_datacopy, db->ix_datacopylen, db->ix_collattr, db->ix_nullsallowed, db->numblobs + 1, thedb->bdb_env, tran, 0, &bdberr); logmsg(LOGMSG_DEBUG, diff --git a/sqlite/CMakeLists.txt b/sqlite/CMakeLists.txt index 2c4690b7f3..380ecdef0a 100644 --- a/sqlite/CMakeLists.txt +++ b/sqlite/CMakeLists.txt @@ -29,6 +29,7 @@ add_library(sqlite ext/comdb2/metrics.c ext/comdb2/netuserfunc.c ext/comdb2/opcode_handlers.c + ext/comdb2/partial_datacopies.c ext/comdb2/permissions.c ext/comdb2/plugins.c ext/comdb2/procedures.c diff --git a/sqlite/ext/comdb2/comdb2systblInt.h b/sqlite/ext/comdb2/comdb2systblInt.h index ea29d26cdd..c03038fc4d 100644 --- a/sqlite/ext/comdb2/comdb2systblInt.h +++ b/sqlite/ext/comdb2/comdb2systblInt.h @@ -67,6 +67,7 @@ int systblNetUserfuncsInit(sqlite3 *db); int systblClusterInit(sqlite3 *db); int systblActiveOsqlsInit(sqlite3 *db); int systblBlkseqInit(sqlite3 *db); +int systblPartialDatacopiesInit(sqlite3 *db); int systblTablePropertiesInit(sqlite3 *db); int systblTimepartInit(sqlite3*db); int systblCronInit(sqlite3*db); diff --git a/sqlite/ext/comdb2/keys.c b/sqlite/ext/comdb2/keys.c index a4405d0368..d780be0266 100644 --- a/sqlite/ext/comdb2/keys.c +++ b/sqlite/ext/comdb2/keys.c @@ -76,6 +76,7 @@ static int systblKeysConnect( #define STKEY_RECNUM 5 #define STKEY_CONDITION 6 #define STKEY_UNIQNULLS 7 +#define STKEY_PARTIALDATACOPY 8 rc = sqlite3_declare_vtab(db, "CREATE TABLE comdb2_keys(tablename," "keyname," @@ -84,7 +85,8 @@ static int systblKeysConnect( "isdatacopy," "isrecnum," "condition," - "uniqnulls)"); + "uniqnulls," + "ispartialdatacopy)"); if( rc==SQLITE_OK ){ pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) ); if( pNew==0 ) return SQLITE_NOMEM; @@ -204,6 +206,11 @@ static int systblKeysColumn( sqlite3_result_text(ctx, pSchema->where, -1, SQLITE_STATIC); break; } + case STKEY_PARTIALDATACOPY: { + sqlite3_result_text(ctx, YESNO(pSchema->flags & SCHEMA_PARTIALDATACOPY), + -1, SQLITE_STATIC); + break; + } } return SQLITE_OK; } diff --git a/sqlite/ext/comdb2/partial_datacopies.c b/sqlite/ext/comdb2/partial_datacopies.c new file mode 100644 index 0000000000..ba35172ac3 --- /dev/null +++ b/sqlite/ext/comdb2/partial_datacopies.c @@ -0,0 +1,98 @@ +/* + Copyright 2022 Bloomberg Finance L.P. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +#include +#include +#include +#include "comdb2.h" +#include "sqlite3.h" +#include "ezsystables.h" + +extern struct dbenv *thedb; + +sqlite3_module systblPartialDatacopiesModule = { + .access_flag = CDB2_ALLOW_USER, + .systable_lock = "comdb2_tables", +}; + +typedef struct systable_partial_datacopies { + char *tablename; + char *keyname; + char *columnname; +} systable_partial_datacopies_t; + +int partial_datacopies_systable_collect(void **data, int *nrecords) +{ + // first find number of records + *nrecords = 0; + struct dbtable *db; + struct schema *schema; + for (int i = 0; i < thedb->num_dbs; i++) { + db = thedb->dbs[i]; + for (int j = 0; j < db->nix; j++) { + schema = db->ixschema[j]; + if (schema->flags & SCHEMA_PARTIALDATACOPY) { + *nrecords += schema->partial_datacopy->nmembers; + } + } + } + + int idx = 0; + struct field *member; + systable_partial_datacopies_t *arr = calloc(*nrecords, sizeof(systable_partial_datacopies_t)); + for (int i = 0; i < thedb->num_dbs; i++) { + db = thedb->dbs[i]; + for (int j = 0; j < db->nix; j++) { + schema = db->ixschema[j]; + if (schema->flags & SCHEMA_PARTIALDATACOPY) { + for (int k = 0; k < schema->partial_datacopy->nmembers; k++) { + member = &schema->partial_datacopy->member[k]; + arr[idx].tablename = strdup(db->tablename); + arr[idx].keyname = strdup(schema->csctag); + arr[idx].columnname = strdup(member->name); + idx++; + } + } + } + } + + *data = arr; + return 0; +} + +void partial_datacopies_systable_free(void *arr, int nrecords) +{ + systable_partial_datacopies_t *parr = (systable_partial_datacopies_t *)arr; + int i; + + for (i = 0; i < nrecords; i++) { + free(parr[i].tablename); + free(parr[i].keyname); + free(parr[i].columnname); + } + free(arr); +} + +int systblPartialDatacopiesInit(sqlite3*db) +{ + return create_system_table( + db, "comdb2_partial_datacopies", &systblPartialDatacopiesModule, + partial_datacopies_systable_collect, partial_datacopies_systable_free, + sizeof(systable_partial_datacopies_t), + CDB2_CSTRING, "tablename", -1, offsetof(systable_partial_datacopies_t, tablename), + CDB2_CSTRING, "keyname", -1, offsetof(systable_partial_datacopies_t, keyname), + CDB2_CSTRING, "columnname", -1, offsetof(systable_partial_datacopies_t, columnname), + SYSTABLE_END_OF_FIELDS); +} diff --git a/sqlite/ext/comdb2/tables.c b/sqlite/ext/comdb2/tables.c index 452fe515ad..f08b0958e9 100644 --- a/sqlite/ext/comdb2/tables.c +++ b/sqlite/ext/comdb2/tables.c @@ -280,6 +280,8 @@ int comdb2SystblInit( rc = sqlite3_create_module(db, "comdb2_logical_operations", &systblLogicalOpsModule, 0); if (rc == SQLITE_OK) rc = sqlite3_create_module(db, "comdb2_systables", &systblSystabsModule, 0); + if (rc == SQLITE_OK) + rc = systblPartialDatacopiesInit(db); if (rc == SQLITE_OK) rc = systblTablePropertiesInit(db); if (rc == SQLITE_OK) diff --git a/sqlite/src/comdb2build.c b/sqlite/src/comdb2build.c index 4ede4cd179..df85384a23 100644 --- a/sqlite/src/comdb2build.c +++ b/sqlite/src/comdb2build.c @@ -2662,6 +2662,14 @@ enum { KEY_DELETED = 1 << 2, KEY_UNIQNULLS = 1 << 3, KEY_RECNUM = 1 << 4, + KEY_PARTIALDATACOPY = 1 << 5, +}; + +struct comdb2_partial_datacopy_field{ + /* Field name */ + char *name; + /* Link */ + LINKC_T(struct comdb2_partial_datacopy_field) lnk; }; struct comdb2_key { @@ -2673,6 +2681,8 @@ struct comdb2_key { char *where; /* Key flags */ uint8_t flags; + /* List of fields in partial datacopy */ + LISTC_T(struct comdb2_partial_datacopy_field) partial_datacopy_list; /* List of columns */ comdb2_index_part_lst idx_col_list; /* Link */ @@ -3287,8 +3297,26 @@ static char *format_csc2(struct comdb2_ddl_context *ctx) strbuf_append(csc2, "dup "); } - if ((key->flags & KEY_DATACOPY) != 0) { + if ((key->flags & (KEY_DATACOPY | KEY_PARTIALDATACOPY)) != 0) { strbuf_append(csc2, "datacopy "); + + if (key->flags & KEY_PARTIALDATACOPY) { + int added = 0; + struct comdb2_partial_datacopy_field *partial_datacopy_field; + + strbuf_append(csc2, "("); + LISTC_FOR_EACH(&key->partial_datacopy_list, partial_datacopy_field, lnk) + { + if (added > 0) { + strbuf_append(csc2, ", "); + } + + strbuf_append(csc2, partial_datacopy_field->name); + + added++; + } + strbuf_append(csc2, ") "); + } } if ((key->flags & KEY_UNIQNULLS) != 0) { @@ -3396,10 +3424,29 @@ static int gen_key_name(struct comdb2_key *key, const char *table, char *out, /* Table name */ SNPRINTF(buf, sizeof(buf), pos, "%s", table) - /* DATACOPY */ - if (key->flags & KEY_DATACOPY) + /* DATACOPY/PARTIALDATACOPY */ + if (key->flags & (KEY_DATACOPY | KEY_PARTIALDATACOPY)) { SNPRINTF(buf, sizeof(buf), pos, "%s", "DATACOPY") + if (key->flags & KEY_PARTIALDATACOPY) { + int added = 0; + struct comdb2_partial_datacopy_field *partial_datacopy_field; + + SNPRINTF(buf, sizeof(buf), pos, "%s", "(") + LISTC_FOR_EACH(&key->partial_datacopy_list, partial_datacopy_field, lnk) + { + if (added > 0) { + SNPRINTF(buf, sizeof(buf), pos, "%s", ", ") + } + + SNPRINTF(buf, sizeof(buf), pos, "%s", partial_datacopy_field->name) + + added++; + } + SNPRINTF(buf, sizeof(buf), pos, "%s", ")") + } + } + /* DUP */ if (key->flags & KEY_DUP) SNPRINTF(buf, sizeof(buf), pos, "%s", "DUP") @@ -3727,6 +3774,8 @@ static char *prepare_csc2(Parse *pParse, struct comdb2_ddl_context *ctx) * Unique * Columns must not allow NULLs * Must be only one per table + * Check that datacopy and partial datacopy are both not set + * Check that partial datacopy columns are valid */ int pk_count = 0; LISTC_FOR_EACH(&ctx->schema->key_list, key, lnk) @@ -3762,6 +3811,27 @@ static char *prepare_csc2(Parse *pParse, struct comdb2_ddl_context *ctx) } } } + + if (key->flags & KEY_PARTIALDATACOPY) { + /* Make sure datacopy and partial datacopy are not set */ + if (key->flags & KEY_DATACOPY) { + pParse->rc = SQLITE_ERROR; + sqlite3ErrorMsg(pParse, "Cannot have datacopy and partial datacopy."); + goto cleanup; + } + + /* Make sure all partial datacopy fields are valid */ + struct comdb2_partial_datacopy_field *partial_datacopy_field; + LISTC_FOR_EACH(&key->partial_datacopy_list, partial_datacopy_field, lnk) + { + if (find_column_by_name(ctx, partial_datacopy_field->name) == 0) { + pParse->rc = SQLITE_ERROR; + sqlite3ErrorMsg(pParse, "Invalid partial datacopy field \"%s\".", partial_datacopy_field->name); + goto cleanup; + } + } + + } } /* @@ -4244,6 +4314,26 @@ static int retrieve_schema(Parse *pParse, struct comdb2_ddl_context *ctx) key->flags |= KEY_UNIQNULLS; } + listc_init(&key->partial_datacopy_list, offsetof(struct comdb2_partial_datacopy_field, lnk)); + + if (schema->ix[i]->flags & SCHEMA_PARTIALDATACOPY) { + key->flags |= KEY_PARTIALDATACOPY; + + struct comdb2_partial_datacopy_field *partial_datacopy_field; + struct schema *partial_datacopy = schema->ix[i]->partial_datacopy; + for (int j = 0; j < partial_datacopy->nmembers; j++) { + partial_datacopy_field = comdb2_calloc(ctx->mem, 1, sizeof(struct comdb2_partial_datacopy_field)); + if (partial_datacopy_field == 0) { + goto oom; + } + partial_datacopy_field->name = comdb2_strdup(ctx->mem, partial_datacopy->member[j].name); + if (partial_datacopy_field->name == 0) { + goto oom; + } + listc_abl(&key->partial_datacopy_list, partial_datacopy_field); + } + } + listc_init(&key->idx_col_list, offsetof(struct comdb2_index_part, lnk)); struct comdb2_column *column; diff --git a/tests/auth.test/t09.expected b/tests/auth.test/t09.expected index 8a21439d05..d950a9d222 100644 --- a/tests/auth.test/t09.expected +++ b/tests/auth.test/t09.expected @@ -242,6 +242,7 @@ (candidate='comdb2_metrics') (candidate='comdb2_net_userfuncs') (candidate='comdb2_opcode_handlers') +(candidate='comdb2_partial_datacopies') (candidate='comdb2_plugins') (candidate='comdb2_procedures') (candidate='comdb2_queues') diff --git a/tests/cdb2sql.test/t00.expected b/tests/cdb2sql.test/t00.expected index 73cabd23f9..f3fec8f130 100644 --- a/tests/cdb2sql.test/t00.expected +++ b/tests/cdb2sql.test/t00.expected @@ -42,6 +42,7 @@ unknown @ls sub-command foo (name='comdb2_metrics') (name='comdb2_net_userfuncs') (name='comdb2_opcode_handlers') +(name='comdb2_partial_datacopies') (name='comdb2_plugins') (name='comdb2_procedures') (name='comdb2_queues') @@ -76,7 +77,7 @@ Columns: (column='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N') Keys: -(keyname='COMDB2_PK', isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL) +(keyname='COMDB2_PK', isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, ispartialdatacopy='N') Constraints: (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t2', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) @@ -95,7 +96,7 @@ Columns: (column='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N') Keys: -(keyname='COMDB2_PK', isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL) +(keyname='COMDB2_PK', isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, ispartialdatacopy='N') Constraints: (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t2', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) @@ -118,7 +119,7 @@ Columns: (column='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N') Keys: -(keyname='COMDB2_PK', isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL) +(keyname='COMDB2_PK', isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, ispartialdatacopy='N') Constraints: (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t2', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) diff --git a/tests/comdb2sys.test/comdb2sys.expected b/tests/comdb2sys.test/comdb2sys.expected index 20ab2ce31d..96888db64e 100644 --- a/tests/comdb2sys.test/comdb2sys.expected +++ b/tests/comdb2sys.test/comdb2sys.expected @@ -49,14 +49,14 @@ (tablename='t3', columnname='value', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t4', columnname='value', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) [select * from comdb2_columns order by columnname, tablename] rc 0 -(tablename='t1', keyname='DUP_VALUE', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='partidx', keyname='UID', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='UID', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='UID1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t3', keyname='UID1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t4', keyname='UID1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='partidx', keyname='UID_WHERE', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition='where value > 10', uniqnulls='N') -(tablename='t1', keyname='VALUE', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='DUP_VALUE', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='partidx', keyname='UID', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='UID', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='UID1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t3', keyname='UID1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t4', keyname='UID1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='partidx', keyname='UID_WHERE', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition='where value > 10', uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='VALUE', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') [select * from comdb2_keys order by keyname, tablename] rc 0 (tablename='partidx', keyname='UID', columnnumber=0, columnname='uid', isdescending='N') (tablename='partidx', keyname='UID_WHERE', columnnumber=0, columnname='uid', isdescending='N') @@ -380,6 +380,7 @@ (name='comdb2_metrics') (name='comdb2_net_userfuncs') (name='comdb2_opcode_handlers') +(name='comdb2_partial_datacopies') (name='comdb2_plugins') (name='comdb2_procedures') (name='comdb2_queues') diff --git a/tests/ddl_no_csc2.test/t00_create_table.expected b/tests/ddl_no_csc2.test/t00_create_table.expected index 180c925bad..b1346c254c 100644 --- a/tests/ddl_no_csc2.test/t00_create_table.expected +++ b/tests/ddl_no_csc2.test/t00_create_table.expected @@ -103,13 +103,13 @@ (tablename='t9', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t10', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t10', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='$KEY_37A25A0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t6', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t6', keyname='$KEY_37496DB0', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t9', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t10', keyname='$KEY_FD8D4AAA', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='$KEY_37A25A0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t6', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t6', keyname='$KEY_37496DB0', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t9', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t10', keyname='$KEY_FD8D4AAA', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int);', csc2='schema { int i @@ -204,15 +204,15 @@ keys (tablename='t7', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t8', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t8', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t2', keyname='$KEY_9C18F596', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='$KEY_2E3CF7EF', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t4', keyname='$KEY_167DCD0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='$KEY_37A25A0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t6', keyname='$KEY_B9974512', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t7', keyname='$KEY_152B02D9', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t8', keyname='$KEY_4F831046', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t8', keyname='$KEY_762F1DF7', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t8', keyname='$KEY_9915B3B9', keynumber=2, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t2', keyname='$KEY_9C18F596', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='$KEY_2E3CF7EF', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t4', keyname='$KEY_167DCD0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='$KEY_37A25A0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t6', keyname='$KEY_B9974512', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t7', keyname='$KEY_152B02D9', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t8', keyname='$KEY_4F831046', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t8', keyname='$KEY_762F1DF7', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t8', keyname='$KEY_9915B3B9', keynumber=2, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (type='table', name='t2', tbl_name='t2', rootpage=4, sql='create table "t2"("i" int, "j" int);', csc2='schema { int i null = yes @@ -306,14 +306,14 @@ keys (tablename='t8', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t9', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t9', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t3', keyname='$KEY_37248BBB', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t6', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t7', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t8', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t9', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t9', keyname='$KEY_827A0A22', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t3', keyname='$KEY_37248BBB', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t6', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t7', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t8', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t9', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t9', keyname='$KEY_827A0A22', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t2', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t3', keyname='$KEY_37248BBB', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t6', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) @@ -569,11 +569,11 @@ constraints (tablename='t3', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t4', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t5', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t3', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t4', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t3', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t4', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t2', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t3', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='Y', iscascadingupdate='N', expr=NULL) (name='$CONSTRAINT_C6A17957', type='FOREIGN KEY', tablename='t4', keyname='COMDB2_PK', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='Y', iscascadingupdate='Y', expr=NULL) @@ -661,9 +661,9 @@ constraints (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t3', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t3', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t3', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t3', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int);', csc2='schema { int i @@ -736,21 +736,21 @@ keys (tablename='t6', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t7', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t7', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='T1_IJ', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='T1_JI', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='DUP1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='DUP2', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t3', keyname='$KEY_7BDB9F9', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t3', keyname='$KEY_B599BB80', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t4', keyname='UNIQ1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t4', keyname='UNIQ2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='$KEY_37A25A0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='$KEY_E8801C19', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='UNIQUE_KEY', keynumber=2, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t5', keyname='T5_IJ', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t5', keyname='DUP_KEY', keynumber=4, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t7', keyname='DUP', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t7', keyname='XXXX', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='T1_IJ', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='T1_JI', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='DUP1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='DUP2', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t3', keyname='$KEY_7BDB9F9', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t3', keyname='$KEY_B599BB80', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t4', keyname='UNIQ1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t4', keyname='UNIQ2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='$KEY_37A25A0B', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='$KEY_E8801C19', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='UNIQUE_KEY', keynumber=2, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t5', keyname='T5_IJ', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t5', keyname='DUP_KEY', keynumber=4, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t7', keyname='DUP', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t7', keyname='XXXX', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int);', csc2='schema { int i null = yes @@ -864,11 +864,11 @@ keys (tablename='t4', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t5', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t5', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t3', keyname='$KEY_DF179048', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t4', keyname='T4_I', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t5', keyname='T5_JI', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t3', keyname='$KEY_DF179048', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t4', keyname='T4_I', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t5', keyname='T5_JI', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int);', csc2='schema { int i @@ -925,7 +925,7 @@ keys [CREATE TABLE t1(unique INT UNIQUE)] failed with rc -3 near "unique": syntax error (part='---------------------------------- PART #49 ----------------------------------') (tablename='t1', columnname='unique', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='$KEY_A513E531', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='$KEY_A513E531', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("unique" int);', csc2='schema { int unique null = yes @@ -949,12 +949,12 @@ keys (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t4', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t4', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='T1_IJ1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='T1_IJ2', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='T1_IJ3', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='T1_IJ4', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='$KEY_A44A20B', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t4', keyname='$KEY_3EE419FC', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='T1_IJ1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='T1_IJ2', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='T1_IJ3', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='T1_IJ4', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='$KEY_A44A20B', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t4', keyname='$KEY_3EE419FC', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (name='$CONSTRAINT_8AAC02E5', type='FOREIGN KEY', tablename='t2', keyname='$KEY_A44A20B', foreigntablename='t1', foreignkeyname='T1_IJ1', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (name='$CONSTRAINT_95177019', type='FOREIGN KEY', tablename='t4', keyname='$KEY_3EE419FC', foreigntablename='t1', foreignkeyname='T1_IJ1', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int);', csc2='schema diff --git a/tests/ddl_no_csc2.test/t01_alter_table.expected b/tests/ddl_no_csc2.test/t01_alter_table.expected index bce455842b..ffabba7480 100644 --- a/tests/ddl_no_csc2.test/t01_alter_table.expected +++ b/tests/ddl_no_csc2.test/t01_alter_table.expected @@ -85,8 +85,8 @@ (tablename='t2', columnname='v', type='cstring', size=11, sqltype='char(10)', varinlinesize=NULL, defaultvalue=''foo'', dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='d', type='datetime', size=11, sqltype='datetime', varinlinesize=NULL, defaultvalue='CURRENT_TIMESTAMP', dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue='10', dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("v" char(10) DEFAULT 'foo', "d" datetime DEFAULT CURRENT_TIMESTAMP, "i" int DEFAULT 10);', csc2='schema { cstring v[11] dbstore = "foo" null = yes @@ -141,12 +141,12 @@ keys (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='k', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='IDX1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t1', keyname='IDX2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t1', keyname='IDX3', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='IDX4', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='COMDB2_PK', keynumber=4, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='IDX1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='IDX1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t1', keyname='IDX2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t1', keyname='IDX3', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='IDX4', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='COMDB2_PK', keynumber=4, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='IDX1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (name='$CONSTRAINT_95177019', type='FOREIGN KEY', tablename='t2', keyname='IDX1', foreigntablename='t1', foreignkeyname='IDX1', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int, "k" int);', csc2='schema { @@ -194,9 +194,9 @@ constraints (tablename='t2', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t3', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t3', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) -(tablename='t1', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t3', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='IDX', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t3', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (name='$CONSTRAINT_95177019', type='FOREIGN KEY', tablename='t2', keyname='IDX', foreigntablename='t1', foreignkeyname='IDX', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int);', csc2='schema { @@ -271,10 +271,10 @@ keys (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t2', columnname='k', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='IDX', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='$KEY_E8BDFAE1', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='IDX', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='$KEY_E8BDFAE1', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (name='$CONSTRAINT_6C9CE8ED', type='FOREIGN KEY', tablename='t2', keyname='$KEY_E8BDFAE1', foreigntablename='t1', foreignkeyname='COMDB2_PK', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int, "k" int);', csc2='schema { @@ -315,7 +315,7 @@ constraints (tablename='t1', columnname='k', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='k', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='N', lastsequence=NULL) -(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') +(tablename='t1', keyname='COMDB2_PK', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int, "k" int);', csc2='schema { int i @@ -376,9 +376,9 @@ constraints (tablename='t2', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t2', columnname='k', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='IDX1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t1', keyname='IDX2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t2', keyname='$KEY_E8BDFAE1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') +(tablename='t1', keyname='IDX1', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t1', keyname='IDX2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t2', keyname='$KEY_E8BDFAE1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') (name='$CONSTRAINT_6C9CE8ED', type='FOREIGN KEY', tablename='t2', keyname='$KEY_E8BDFAE1', foreigntablename='t1', foreignkeyname='IDX1', iscascadingdelete='N', iscascadingupdate='N', expr=NULL) (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int, "j" int, "k" int);', csc2='schema { diff --git a/tests/ddl_no_csc2.test/t02_create_index.expected b/tests/ddl_no_csc2.test/t02_create_index.expected index c7c793bc90..8ef9d6630a 100644 --- a/tests/ddl_no_csc2.test/t02_create_index.expected +++ b/tests/ddl_no_csc2.test/t02_create_index.expected @@ -17,18 +17,18 @@ (tablename='t3', columnname='j', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t4', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) (tablename='t5', columnname='i', type='int', size=5, sqltype='int', varinlinesize=NULL, defaultvalue=NULL, dbload=NULL, isnullable='Y', lastsequence=NULL) -(tablename='t1', keyname='IDX1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='IDX2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y') -(tablename='t1', keyname='IDX3', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='IDX4', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='IDX5', keynumber=4, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='IDX6', keynumber=5, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t1', keyname='IDX7', keynumber=6, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='IDX1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition='WHERE (j > 10) ', uniqnulls='N') -(tablename='t2', keyname='IDX3', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t2', keyname='IDX4', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t3', keyname='IDX1', keynumber=0, isunique='N', isdatacopy='Y', isrecnum='N', condition=NULL, uniqnulls='N') -(tablename='t3', keyname='IDX2', keynumber=1, isunique='N', isdatacopy='Y', isrecnum='N', condition='WHERE (j > 10) ', uniqnulls='N') +(tablename='t1', keyname='IDX1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='IDX2', keynumber=1, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='Y', ispartialdatacopy='N') +(tablename='t1', keyname='IDX3', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='IDX4', keynumber=3, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='IDX5', keynumber=4, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='IDX6', keynumber=5, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t1', keyname='IDX7', keynumber=6, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='IDX1', keynumber=0, isunique='N', isdatacopy='N', isrecnum='N', condition='WHERE (j > 10) ', uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='IDX3', keynumber=1, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t2', keyname='IDX4', keynumber=2, isunique='N', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t3', keyname='IDX1', keynumber=0, isunique='N', isdatacopy='Y', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='N') +(tablename='t3', keyname='IDX2', keynumber=1, isunique='N', isdatacopy='Y', isrecnum='N', condition='WHERE (j > 10) ', uniqnulls='N', ispartialdatacopy='N') (type='table', name='t1', tbl_name='t1', rootpage=4, sql='create table "t1"("i" int);', csc2='schema { int i null = yes diff --git a/tests/instant_sc.test/t08.req b/tests/instant_sc.test/t08.req index 892729b73e..b0aa6baa1e 100644 --- a/tests/instant_sc.test/t08.req +++ b/tests/instant_sc.test/t08.req @@ -17,5 +17,5 @@ tag "full" keys { "0" = j - datacopy "1" = i + datacopy(k) "1" = i } diff --git a/tests/instant_sc.test/t12.req b/tests/instant_sc.test/t12.req index a27073c452..15bfbff6ce 100644 --- a/tests/instant_sc.test/t12.req +++ b/tests/instant_sc.test/t12.req @@ -1,4 +1,4 @@ -//change dbstore only; old comdb2 will rebuild, new one will just increment version +//change dbstore only (and revert partial datacopy back to full datacopy); old comdb2 will rebuild, new one will just increment version schema { int k dbstore=9999 diff --git a/tests/partial_datacopy.test/Makefile b/tests/partial_datacopy.test/Makefile new file mode 100644 index 0000000000..2d39e80074 --- /dev/null +++ b/tests/partial_datacopy.test/Makefile @@ -0,0 +1,8 @@ +ifeq ($(TESTSROOTDIR),) + include ../testcase.mk +else + include $(TESTSROOTDIR)/testcase.mk +endif +ifeq ($(TEST_TIMEOUT),) + export TEST_TIMEOUT=3m +endif diff --git a/tests/partial_datacopy.test/runit b/tests/partial_datacopy.test/runit new file mode 100755 index 0000000000..6ed830baa2 --- /dev/null +++ b/tests/partial_datacopy.test/runit @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +bash -n "$0" | exit 1 + +${TESTSROOTDIR}/tools/compare_results.sh -s -d $1 -r sql +[ $? -eq 0 ] || exit 1 +exit 0 diff --git a/tests/partial_datacopy.test/t00.expected b/tests/partial_datacopy.test/t00.expected new file mode 100644 index 0000000000..9049234dc5 --- /dev/null +++ b/tests/partial_datacopy.test/t00.expected @@ -0,0 +1,33 @@ +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy datacopy(b, c) "a" = a + } +}] failed with rc 240 Error at line 8: CANNOT HAVE DATACOPY AND PARTIAL DATACOPY. +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) datacopy "a" = a + } +}] failed with rc 240 Error at line 8: CANNOT HAVE DATACOPY AND PARTIAL DATACOPY. +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) datacopy(d) "a" = a + } +}] failed with rc 240 Error at line 8: CANNOT HAVE MULTIPLE PARTIAL DATACOPIES. diff --git a/tests/partial_datacopy.test/t00.sql b/tests/partial_datacopy.test/t00.sql new file mode 100644 index 0000000000..f0bd5c50f4 --- /dev/null +++ b/tests/partial_datacopy.test/t00.sql @@ -0,0 +1,35 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy datacopy(b, c) "a" = a + } +};$$ + +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) datacopy "a" = a + } +};$$ + +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) datacopy(d) "a" = a + } +};$$ diff --git a/tests/partial_datacopy.test/t01.expected b/tests/partial_datacopy.test/t01.expected new file mode 100644 index 0000000000..764a32f0e3 --- /dev/null +++ b/tests/partial_datacopy.test/t01.expected @@ -0,0 +1,11 @@ +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy() "a" = a + } +}] failed with rc 240 ERROR at line 8: syntax error: ) diff --git a/tests/partial_datacopy.test/t01.sql b/tests/partial_datacopy.test/t01.sql new file mode 100644 index 0000000000..b812b115f1 --- /dev/null +++ b/tests/partial_datacopy.test/t01.sql @@ -0,0 +1,11 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy() "a" = a + } +};$$ diff --git a/tests/partial_datacopy.test/t02.expected b/tests/partial_datacopy.test/t02.expected new file mode 100644 index 0000000000..51a136f8ee --- /dev/null +++ b/tests/partial_datacopy.test/t02.expected @@ -0,0 +1,33 @@ +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(e) "a" = a + } +}] failed with rc 240 Error at line 8: SYMBOL NOT FOUND: e. +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, e, c) "a" = a + } +}] failed with rc 240 Error at line 8: SYMBOL NOT FOUND: e. +[create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, e, c, a, f, g) "a" = a + } +}] failed with rc 240 Error at line 8: SYMBOL NOT FOUND: e.Error at line 8: SYMBOL NOT FOUND: f.Error at line 8: SYMBOL NOT FOUND: g. diff --git a/tests/partial_datacopy.test/t02.sql b/tests/partial_datacopy.test/t02.sql new file mode 100644 index 0000000000..19037cf397 --- /dev/null +++ b/tests/partial_datacopy.test/t02.sql @@ -0,0 +1,35 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(e) "a" = a + } +};$$ + +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, e, c) "a" = a + } +};$$ + +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, e, c, a, f, g) "a" = a + } +};$$ diff --git a/tests/partial_datacopy.test/t03.expected b/tests/partial_datacopy.test/t03.expected new file mode 100644 index 0000000000..a919cf4ce0 --- /dev/null +++ b/tests/partial_datacopy.test/t03.expected @@ -0,0 +1,24 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='b') +(tablename='t', keyname='A', columnname='c') +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) diff --git a/tests/partial_datacopy.test/t03.sql b/tests/partial_datacopy.test/t03.sql new file mode 100644 index 0000000000..655a4fc5ff --- /dev/null +++ b/tests/partial_datacopy.test/t03.sql @@ -0,0 +1,20 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) "a" = a + } +};$$ + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t04.expected b/tests/partial_datacopy.test/t04.expected new file mode 100644 index 0000000000..685d9d81be --- /dev/null +++ b/tests/partial_datacopy.test/t04.expected @@ -0,0 +1,25 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='b') +(tablename='t', keyname='A', columnname='c') +(tablename='t', keyname='A', columnname='d') +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) diff --git a/tests/partial_datacopy.test/t04.sql b/tests/partial_datacopy.test/t04.sql new file mode 100644 index 0000000000..1c423860b5 --- /dev/null +++ b/tests/partial_datacopy.test/t04.sql @@ -0,0 +1,20 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, b, b, b, c, c, c, c, b, c, b, c, b, d) "a" = a + } +};$$ + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t05.expected b/tests/partial_datacopy.test/t05.expected new file mode 100644 index 0000000000..98aeda05da --- /dev/null +++ b/tests/partial_datacopy.test/t05.expected @@ -0,0 +1,39 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='a') +(tablename='t2', keyname='ABCD', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t2', keyname='ABCD', columnname='a') +(tablename='t2', keyname='ABCD', columnname='b') +(tablename='t2', keyname='ABCD', columnname='c') +(tablename='t2', keyname='ABCD', columnname='d') +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1) +(a=5) +(a=9) +(a=13) +(a=17) +(a=21) +(a=25) +(a=29) +(a=33) +(a=37) +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) diff --git a/tests/partial_datacopy.test/t05.sql b/tests/partial_datacopy.test/t05.sql new file mode 100644 index 0000000000..7b14c26525 --- /dev/null +++ b/tests/partial_datacopy.test/t05.sql @@ -0,0 +1,39 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(a) "a" = a + } +};$$ + +create table t2 { + schema { + int a + int b + int c + int d + } + keys { + datacopy(a, b, c, d) "abcd" = a + b + c + d + } +};$$ + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +select * from comdb2_keys where tablename='t2'; +select * from comdb2_partial_datacopies where tablename='t2'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a from t where a < 40; + +insert into t2 with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t2 where a < 40; + +drop table t; +drop table t2; diff --git a/tests/partial_datacopy.test/t06.expected b/tests/partial_datacopy.test/t06.expected new file mode 100644 index 0000000000..2bfd606567 --- /dev/null +++ b/tests/partial_datacopy.test/t06.expected @@ -0,0 +1,25 @@ +(tablename='t', keyname='AC', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='AC', columnname='a') +(tablename='t', keyname='AC', columnname='b') +(tablename='t', keyname='AC', columnname='c') +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) diff --git a/tests/partial_datacopy.test/t06.sql b/tests/partial_datacopy.test/t06.sql new file mode 100644 index 0000000000..3e9604b7ba --- /dev/null +++ b/tests/partial_datacopy.test/t06.sql @@ -0,0 +1,21 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(a, b, c) "ac" = a + c + } +};$$ + + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t07.expected b/tests/partial_datacopy.test/t07.expected new file mode 100644 index 0000000000..4385550178 --- /dev/null +++ b/tests/partial_datacopy.test/t07.expected @@ -0,0 +1,24 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='c') +(tablename='t', keyname='A', columnname='b') +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) diff --git a/tests/partial_datacopy.test/t07.sql b/tests/partial_datacopy.test/t07.sql new file mode 100644 index 0000000000..b4eb202002 --- /dev/null +++ b/tests/partial_datacopy.test/t07.sql @@ -0,0 +1,21 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(c, b) "a" = a + } +};$$ + + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t08.expected b/tests/partial_datacopy.test/t08.expected new file mode 100644 index 0000000000..d1e48ab03f --- /dev/null +++ b/tests/partial_datacopy.test/t08.expected @@ -0,0 +1,47 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='b') +(tablename='t', keyname='A', columnname='c') +(rows inserted=25) +(a=1, b='cdb2', c=3, d=4) +(a=5, b='cdb6', c=7, d=8) +(a=9, b='cdb10', c=11, d=12) +(a=13, b='cdb14', c=15, d=16) +(a=17, b='cdb18', c=19, d=20) +(a=21, b='cdb22', c=23, d=24) +(a=25, b='cdb26', c=27, d=28) +(a=29, b='cdb30', c=31, d=32) +(a=33, b='cdb34', c=35, d=36) +(a=37, b='cdb38', c=39, d=40) +(a=1, b='cdb2', c=3) +(a=5, b='cdb6', c=7) +(a=9, b='cdb10', c=11) +(a=13, b='cdb14', c=15) +(a=17, b='cdb18', c=19) +(a=21, b='cdb22', c=23) +(a=25, b='cdb26', c=27) +(a=29, b='cdb30', c=31) +(a=33, b='cdb34', c=35) +(a=37, b='cdb38', c=39) +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='b') +(tablename='t', keyname='A', columnname='c') +(a=1, b='cdb2', c=3, d=4) +(a=5, b='cdb6', c=7, d=8) +(a=9, b='cdb10', c=11, d=12) +(a=13, b='cdb14', c=15, d=16) +(a=17, b='cdb18', c=19, d=20) +(a=21, b='cdb22', c=23, d=24) +(a=25, b='cdb26', c=27, d=28) +(a=29, b='cdb30', c=31, d=32) +(a=33, b='cdb34', c=35, d=36) +(a=37, b='cdb38', c=39, d=40) +(a=1, b='cdb2', c=3) +(a=5, b='cdb6', c=7) +(a=9, b='cdb10', c=11) +(a=13, b='cdb14', c=15) +(a=17, b='cdb18', c=19) +(a=21, b='cdb22', c=23) +(a=25, b='cdb26', c=27) +(a=29, b='cdb30', c=31) +(a=33, b='cdb34', c=35) +(a=37, b='cdb38', c=39) diff --git a/tests/partial_datacopy.test/t08.sql b/tests/partial_datacopy.test/t08.sql new file mode 100644 index 0000000000..b0272da9e4 --- /dev/null +++ b/tests/partial_datacopy.test/t08.sql @@ -0,0 +1,39 @@ +create table t { + schema { + int a + vutf8 b[6] + int c + int d + } + keys { + datacopy(b, c) "a" = a + } +};$$ + + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, "cdb" || (n + 1), n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +alter table t { + schema { + int a + vutf8 b[4] + int c + int d + } + keys { + datacopy(b, c) "a" = a + } +};$$ + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t09.expected b/tests/partial_datacopy.test/t09.expected new file mode 100644 index 0000000000..0683c4430c --- /dev/null +++ b/tests/partial_datacopy.test/t09.expected @@ -0,0 +1,24 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='c') +(tablename='t', keyname='A', columnname='b') +(rows inserted=25) +(a=1, b='bbb2', c='ccc3', d=4) +(a=5, b='bbb6', c='ccc7', d=8) +(a=9, b='bbb10', c='ccc11', d=12) +(a=13, b='bbb14', c='ccc15', d=16) +(a=17, b='bbb18', c='ccc19', d=20) +(a=21, b='bbb22', c='ccc23', d=24) +(a=25, b='bbb26', c='ccc27', d=28) +(a=29, b='bbb30', c='ccc31', d=32) +(a=33, b='bbb34', c='ccc35', d=36) +(a=37, b='bbb38', c='ccc39', d=40) +(a=1, b='bbb2', c='ccc3') +(a=5, b='bbb6', c='ccc7') +(a=9, b='bbb10', c='ccc11') +(a=13, b='bbb14', c='ccc15') +(a=17, b='bbb18', c='ccc19') +(a=21, b='bbb22', c='ccc23') +(a=25, b='bbb26', c='ccc27') +(a=29, b='bbb30', c='ccc31') +(a=33, b='bbb34', c='ccc35') +(a=37, b='bbb38', c='ccc39') diff --git a/tests/partial_datacopy.test/t09.sql b/tests/partial_datacopy.test/t09.sql new file mode 100644 index 0000000000..231c298954 --- /dev/null +++ b/tests/partial_datacopy.test/t09.sql @@ -0,0 +1,21 @@ +create table t { + schema { + int a + vutf8 b[4] + vutf8 c[4] + int d + } + keys { + datacopy(c, b) "a" = a + } +};$$ + + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, "bbb" || (n + 1), "ccc" || (n + 2), n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t10.expected b/tests/partial_datacopy.test/t10.expected new file mode 100644 index 0000000000..f4fe04d0b3 --- /dev/null +++ b/tests/partial_datacopy.test/t10.expected @@ -0,0 +1,4 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='b') +(rows inserted=1) +[insert into t values (1,2,1)] failed with rc 299 add key constraint duplicate key 'A' on table 't' index 0 diff --git a/tests/partial_datacopy.test/t10.sql b/tests/partial_datacopy.test/t10.sql new file mode 100644 index 0000000000..6149d799db --- /dev/null +++ b/tests/partial_datacopy.test/t10.sql @@ -0,0 +1,19 @@ +create table t { + schema { + int a + int b + int c + } + keys { + datacopy(b) "a" = a + } +};$$ + + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t values (1,1,1); +insert into t values (1,2,1); + +drop table t; diff --git a/tests/partial_datacopy.test/t11.expected b/tests/partial_datacopy.test/t11.expected new file mode 100644 index 0000000000..6ba41cedb2 --- /dev/null +++ b/tests/partial_datacopy.test/t11.expected @@ -0,0 +1,25 @@ +(tablename='t', keyname='A', keynumber=0, isunique='Y', isdatacopy='N', isrecnum='N', condition=NULL, uniqnulls='N', ispartialdatacopy='Y') +(tablename='t', keyname='A', columnname='a') +(tablename='t', keyname='A', columnname='c') +(tablename='t', keyname='A', columnname='b') +(rows inserted=25) +(a=1, b='bbb2', c='ccc3', d=4) +(a=5, b='bbb6', c='ccc7', d=8) +(a=9, b='bbb10', c='ccc11', d=12) +(a=13, b='bbb14', c='ccc15', d=16) +(a=17, b='bbb18', c='ccc19', d=20) +(a=21, b='bbb22', c='ccc23', d=24) +(a=25, b='bbb26', c='ccc27', d=28) +(a=29, b='bbb30', c='ccc31', d=32) +(a=33, b='bbb34', c='ccc35', d=36) +(a=37, b='bbb38', c='ccc39', d=40) +(a=1, b='bbb2', c='ccc3') +(a=5, b='bbb6', c='ccc7') +(a=9, b='bbb10', c='ccc11') +(a=13, b='bbb14', c='ccc15') +(a=17, b='bbb18', c='ccc19') +(a=21, b='bbb22', c='ccc23') +(a=25, b='bbb26', c='ccc27') +(a=29, b='bbb30', c='ccc31') +(a=33, b='bbb34', c='ccc35') +(a=37, b='bbb38', c='ccc39') diff --git a/tests/partial_datacopy.test/t11.sql b/tests/partial_datacopy.test/t11.sql new file mode 100644 index 0000000000..c2e0ad679f --- /dev/null +++ b/tests/partial_datacopy.test/t11.sql @@ -0,0 +1,21 @@ +create table t { + schema { + int a + vutf8 b[4] + vutf8 c[4] + int d + } + keys { + datacopy(a, c, b) "a" = (int)"a + 1" + } +};$$ + + +select * from comdb2_keys where tablename='t'; +select * from comdb2_partial_datacopies where tablename='t'; + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, "bbb" || (n + 1), "ccc" || (n + 2), n + 3 from r; +select * from t where a + 1 < 40; +select a, b, c from t where a + 1 < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t12.expected b/tests/partial_datacopy.test/t12.expected new file mode 100644 index 0000000000..22b94396c5 --- /dev/null +++ b/tests/partial_datacopy.test/t12.expected @@ -0,0 +1,2 @@ +(rows inserted=25) +(out='Verify succeeded.') diff --git a/tests/partial_datacopy.test/t12.sql b/tests/partial_datacopy.test/t12.sql new file mode 100644 index 0000000000..a00541305c --- /dev/null +++ b/tests/partial_datacopy.test/t12.sql @@ -0,0 +1,16 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) "a" = a + } +};$$ + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +exec procedure sys.cmd.verify("t"); + +drop table t; diff --git a/tests/partial_datacopy.test/t13.expected b/tests/partial_datacopy.test/t13.expected new file mode 100644 index 0000000000..96e17bd1a1 --- /dev/null +++ b/tests/partial_datacopy.test/t13.expected @@ -0,0 +1,40 @@ +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) diff --git a/tests/partial_datacopy.test/t13.sql b/tests/partial_datacopy.test/t13.sql new file mode 100644 index 0000000000..fc68c421b0 --- /dev/null +++ b/tests/partial_datacopy.test/t13.sql @@ -0,0 +1,23 @@ +create table t { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) "a" = a + } +};$$ + +set transaction read committed; +begin; +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; +commit; + +select * from t where a < 40; +select a, b, c from t where a < 40; + +drop table t; diff --git a/tests/partial_datacopy.test/t14.expected b/tests/partial_datacopy.test/t14.expected new file mode 100644 index 0000000000..15d050fd91 --- /dev/null +++ b/tests/partial_datacopy.test/t14.expected @@ -0,0 +1,22 @@ +(rows inserted=25) +(a=1, b=2, c=3, d=4) +(a=5, b=6, c=7, d=8) +(a=9, b=10, c=11, d=12) +(a=13, b=14, c=15, d=16) +(a=17, b=18, c=19, d=20) +(a=21, b=22, c=23, d=24) +(a=25, b=26, c=27, d=28) +(a=29, b=30, c=31, d=32) +(a=33, b=34, c=35, d=36) +(a=37, b=38, c=39, d=40) +(a=1, b=2, c=3) +(a=5, b=6, c=7) +(a=9, b=10, c=11) +(a=13, b=14, c=15) +(a=17, b=18, c=19) +(a=21, b=22, c=23) +(a=25, b=26, c=27) +(a=29, b=30, c=31) +(a=33, b=34, c=35) +(a=37, b=38, c=39) +(out='Verify succeeded.') diff --git a/tests/partial_datacopy.test/t14.sql b/tests/partial_datacopy.test/t14.sql new file mode 100644 index 0000000000..8bd0a30a26 --- /dev/null +++ b/tests/partial_datacopy.test/t14.sql @@ -0,0 +1,19 @@ +create table t options odh off, rec none, blobfield none, ipu off, isc off { + schema { + int a + int b + int c + int d + } + keys { + datacopy(b, c) "a" = a + } +};$$ + +insert into t with recursive r(n) as (select 1 union all select n + 4 from r where n < 97) select n, n + 1, n + 2, n + 3 from r; +select * from t where a < 40; +select a, b, c from t where a < 40; + +exec procedure sys.cmd.verify("t"); + +drop table t; diff --git a/tests/sc_partial_datacopy.test/Makefile b/tests/sc_partial_datacopy.test/Makefile new file mode 100644 index 0000000000..4f1a0fb623 --- /dev/null +++ b/tests/sc_partial_datacopy.test/Makefile @@ -0,0 +1,8 @@ +ifeq ($(TESTSROOTDIR),) + include ../testcase.mk +else + include $(TESTSROOTDIR)/testcase.mk +endif +ifeq ($(TEST_TIMEOUT),) + export TEST_TIMEOUT=10m +endif diff --git a/tests/sc_partial_datacopy.test/logicalsc.testopts b/tests/sc_partial_datacopy.test/logicalsc.testopts new file mode 100644 index 0000000000..a0142013e6 --- /dev/null +++ b/tests/sc_partial_datacopy.test/logicalsc.testopts @@ -0,0 +1 @@ +on logical_live_sc diff --git a/tests/sc_partial_datacopy.test/lrl.options b/tests/sc_partial_datacopy.test/lrl.options new file mode 100644 index 0000000000..222a44dcc8 --- /dev/null +++ b/tests/sc_partial_datacopy.test/lrl.options @@ -0,0 +1,3 @@ +maxosqltransfer 500000 +logmsg level info +dont_forbid_ulonglong diff --git a/tests/sc_partial_datacopy.test/runit b/tests/sc_partial_datacopy.test/runit new file mode 100755 index 0000000000..536835abfb --- /dev/null +++ b/tests/sc_partial_datacopy.test/runit @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +maxt1=100000 + +wrpid=-1 + +# Grab my database name. +dbnm=$1 + +# Verify that the user at least supplied a dbname +if [[ -z "$dbnm" ]]; then + + echo "Testcase requires argument." + exit 1 + +fi + +function errquit +{ + typeset msg=$1 + + echo "ERROR: $msg" + echo "Testcase failed." + + [[ $wrpid != "-1" ]] && kill -9 $wrpid >/dev/null 2>&1 + + exit 1 +} + +function do_verify +{ + typeset cnt=0 + + cdb2sql ${CDB2_OPTIONS} $dbnm default "exec procedure sys.cmd.verify('t1')" &> verify.out + if ! grep succeeded verify.out > /dev/null ; then + errquit "Verify failed. see verify.out" + fi +} + +function update_t1 +{ + typeset id + typeset out + + id=$(( RANDOM % (maxt1) )) + cdb2sql ${CDB2_OPTIONS} $dbnm default "update t1 set time = `echo $(($(date +%s%N)/1000000))` where id = $id" >> update.log + if [[ $? != 0 ]]; then + errquit "update failed, see update.log" + fi +} + +function writer +{ + while true; do + update_t1 + sleep 0.02 + done +} + +cdb2sql ${CDB2_OPTIONS} $dbnm default - <<"EOF" +drop table if exists t1 +create table t1 { + tag ondisk { + longlong id + u_longlong time + } + keys { + datacopy(time) "ID" = id + } +}$$ +EOF + +cdb2sql ${CDB2_OPTIONS} $dbnm default "WITH RECURSIVE cnt(x) AS (SELECT 1 UNION ALL SELECT x+1 FROM cnt LIMIT $maxt1) insert into t1(id, time) SELECT x, `echo $(($(date +%s%N)/1000000))` FROM cnt" +if [[ $? != 0 ]]; then + echo "initial insert failed" + exit 1 +fi + +# Trap to errquit if the user presses Ctrl-C +trap "errquit \"Cancelling test on INT EXIT\"" INT EXIT + +writer & +wrpid=$! +echo "Background writer pid: $wrpid" + +echo "Starting schemachange" +cdb2sql ${CDB2_OPTIONS} $dbnm default "PUT SCHEMACHANGE COMMITSLEEP 3" +cdb2sql ${CDB2_OPTIONS} $dbnm default "PUT SCHEMACHANGE CONVERTSLEEP 3" + +cdb2sql ${CDB2_OPTIONS} $dbnm default - <<"EOF" +alter table t1 { + tag ondisk { + longlong id + longlong time + } + keys { + datacopy(id, time) "ID" = id + } +}$$ +EOF +if [[ $? != 0 ]]; then + errquit "schemachange 1 failed" +fi +do_verify + +cdb2sql ${CDB2_OPTIONS} $dbnm default - <<"EOF" +alter table t1 { + tag ondisk { + longlong id + double time + } + keys { + datacopy(time) "ID" = id + } +}$$ +EOF +if [[ $? != 0 ]]; then + errquit "schemachange 2 failed" +fi +do_verify + +cdb2sql ${CDB2_OPTIONS} $dbnm default - <<"EOF" +alter table t1 { + tag ondisk { + longlong id + u_longlong time + } + keys { + datacopy(time) "ID" = (longlong)"id*1" + } +}$$ +EOF +if [[ $? != 0 ]]; then + errquit "schemachange 3 failed" +fi +do_verify + +# Remove trap-command. +trap - INT EXIT + +[[ $wrpid != "-1" ]] && kill -9 $wrpid >/dev/null 2>&1 + +echo "Testcase passed." +exit 0 diff --git a/tests/userschema.test/t00.expected b/tests/userschema.test/t00.expected index 084a062308..7759fb99ff 100644 --- a/tests/userschema.test/t00.expected +++ b/tests/userschema.test/t00.expected @@ -29,6 +29,7 @@ (tablename='comdb2_metrics', username='mohit', READ='Y', WRITE='Y', DDL='Y') (tablename='comdb2_net_userfuncs', username='mohit', READ='Y', WRITE='Y', DDL='Y') (tablename='comdb2_opcode_handlers', username='mohit', READ='Y', WRITE='Y', DDL='Y') +(tablename='comdb2_partial_datacopies', username='mohit', READ='Y', WRITE='Y', DDL='Y') (tablename='comdb2_plugins', username='mohit', READ='Y', WRITE='Y', DDL='Y') (tablename='comdb2_procedures', username='mohit', READ='Y', WRITE='Y', DDL='Y') (tablename='comdb2_queues', username='mohit', READ='Y', WRITE='Y', DDL='Y') diff --git a/tools/cdb2sql/cdb2sql.cpp b/tools/cdb2sql/cdb2sql.cpp index 379b7e9db6..6a953b0482 100644 --- a/tools/cdb2sql/cdb2sql.cpp +++ b/tools/cdb2sql/cdb2sql.cpp @@ -924,7 +924,7 @@ static int process_escape(const char *cmdstr) fprintf(out, "Keys:\n"); snprintf(sql, sizeof(sql), "select keyname, isunique, isdatacopy, isrecnum, " - "condition from comdb2_keys where tablename = '%s'", + "condition, ispartialdatacopy from comdb2_keys where tablename = '%s'", tok); rc = run_statement(sql, 0, NULL, &start_time_ms, &run_time_ms); if (rc != 0) {