Changeset: 2072196020bf for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2072196020bf Added Files: sql/test/BugTracker-2019/Tests/next-get-value-bulk.Bug-6766.stable.err Modified Files: clients/Tests/MAL-signatures.stable.out clients/Tests/MAL-signatures.stable.out.int128 sql/backends/monet5/sql.c sql/backends/monet5/sql.h sql/backends/monet5/sql.mal sql/storage/store_sequence.c sql/storage/store_sequence.h sql/test/BugTracker-2018/Tests/negative-sequences.Bug-6665.stable.err sql/test/BugTracker-2019/Tests/next-get-value-bulk.Bug-6766.sql sql/test/BugTracker-2019/Tests/next-get-value-bulk.Bug-6766.stable.out Branch: default Log Message:
Merge with Nov2019 diffs (truncated from 736 to 300 lines): diff --git a/clients/Tests/MAL-signatures.stable.out b/clients/Tests/MAL-signatures.stable.out --- a/clients/Tests/MAL-signatures.stable.out +++ b/clients/Tests/MAL-signatures.stable.out @@ -8973,6 +8973,9 @@ stdout of test 'MAL-signatures` in direc [ "batsql", "diff", "pattern batsql.diff(b:bat[:any_1]):bat[:bit] ", "SQLdiff;", "return true if cur != prev row" ] [ "batsql", "diff", "pattern batsql.diff(p:bat[:bit], b:bat[:any_1]):bat[:bit] ", "SQLdiff;", "return true if cur != prev row" ] [ "batsql", "first_value", "pattern batsql.first_value(b:bat[:any_1], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLfirst_value;", "return the first value of groups" ] +[ "batsql", "get_value", "pattern batsql.get_value(sname:bat[:str], sequence:str):bat[:lng] ", "mvc_bat_get_value;", "return the current value of the sequence" ] +[ "batsql", "get_value", "pattern batsql.get_value(sname:str, sequence:bat[:str]):bat[:lng] ", "mvc_bat_schema_sequences_get_value;", "return the current value of sequences" ] +[ "batsql", "get_value", "pattern batsql.get_value(sname:bat[:str], sequence:bat[:str]):bat[:lng] ", "mvc_bat_schemas_sequences_get_value;", "return the current value of sequences" ] [ "batsql", "lag", "pattern batsql.lag(b:bat[:any_1], l:any_2, d:any_1, p:any_3, o:any_4):bat[:any_1] ", "SQLlag;", "return the value in the previous 'l' row in the partition or 'd' if non existent" ] [ "batsql", "lag", "pattern batsql.lag(b:bat[:any_1], l:any_2, d:bat[:any_1], p:any_3, o:any_4):bat[:any_1] ", "SQLlag;", "return the value in the previous 'l' row in the partition or 'd' if non existent" ] [ "batsql", "lag", "pattern batsql.lag(b:bat[:any_1], l:any_2, p:any_3, o:any_4):bat[:any_1] ", "SQLlag;", "return the value in the previous 'l' row in the partition or NULL if non existent" ] @@ -8991,6 +8994,8 @@ stdout of test 'MAL-signatures` in direc [ "batsql", "max", "pattern batsql.max(b:bat[:any_1], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLmax;", "return the maximum of groups" ] [ "batsql", "min", "pattern batsql.min(b:bat[:any_1], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLmin;", "return the minimum of groups" ] [ "batsql", "next_value", "pattern batsql.next_value(sname:bat[:str], sequence:str):bat[:lng] ", "mvc_bat_next_value;", "return the next value of the sequence" ] +[ "batsql", "next_value", "pattern batsql.next_value(sname:str, sequence:bat[:str]):bat[:lng] ", "mvc_bat_schema_sequences_next_value;", "return the next value of sequences" ] +[ "batsql", "next_value", "pattern batsql.next_value(sname:bat[:str], sequence:bat[:str]):bat[:lng] ", "mvc_bat_schemas_sequences_next_value;", "return the next value of sequences" ] [ "batsql", "nth_value", "pattern batsql.nth_value(b:bat[:any_1], n:any_2, s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLnth_value;", "return the nth value of each group" ] [ "batsql", "nth_value", "pattern batsql.nth_value(b:bat[:any_1], n:bat[:any_2], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLnth_value;", "return the nth value of each group" ] [ "batsql", "ntile", "pattern batsql.ntile(b:bat[:any_1], n:any_2, p:any_3, o:any_4):bat[:any_2] ", "SQLntile;", "return the groups divided as equally as possible" ] @@ -11666,11 +11671,12 @@ stdout of test 'MAL-signatures` in direc [ "sql", "export_table", "unsafe pattern sql.export_table(fname:str, fmt:str, colsep:str, recsep:str, qout:str, nullrep:str, onclient:int, tbl:bat[:str], attr:bat[:str], tpe:bat[:str], len:bat[:int], scale:bat[:int], cols:any...):int ", "mvc_export_row_wrap;", "Prepare a table result set for the COPY INTO stream" ] [ "sql", "export_table", "unsafe pattern sql.export_table(fname:str, fmt:str, colsep:str, recsep:str, qout:str, nullrep:str, onclient:int, tbl:bat[:str], attr:bat[:str], tpe:bat[:str], len:bat[:int], scale:bat[:int], cols:bat[:any]...):int ", "mvc_export_table_wrap;", "Prepare a table result set for the COPY INTO stream" ] [ "sql", "first_value", "pattern sql.first_value(b:any_1, s:lng, e:lng):any_1 ", "SQLfirst_value;", "return the first value of groups" ] -[ "sql", "flush_log", "command sql.flush_log():void ", "SQLflush_log;", "flush the log now" ] +[ "sql", "flush_log", "command sql.flush_log():void ", "SQLflush_log;", "start flushing the write ahead log" ] [ "sql", "getVariable", "pattern sql.getVariable(mvc:int, varname:str):any_1 ", "getVariable;", "Get the value of a session variable" ] [ "sql", "getVersion", "command sql.getVersion(clientid:int):lng ", "mvc_getVersion;", "Return the database version identifier for a client." ] [ "sql", "get_value", "pattern sql.get_value(sname:str, sequence:str):lng ", "mvc_get_value;", "return the current value of the sequence" ] [ "sql", "grow", "pattern sql.grow(tid:bat[:oid], X_0:any_1):int ", "mvc_grow_wrap;", "Resize the tid column of a declared table." ] +[ "sql", "hot_snapshot", "command sql.hot_snapshot(tarfile:str):void ", "SQLhot_snapshot;", "Write db snapshot to the given tar(.gz) file" ] [ "sql", "importTable", "unsafe pattern sql.importTable(sname:str, tname:str, onclient:int, fname:str...):bat[:any]... ", "mvc_bin_import_table_wrap;", "Import a table from the files (fname)" ] [ "sql", "include", "pattern sql.include(fname:str):void ", "SQLinclude;", "Compile and execute a sql statements on the file" ] [ "sql", "lag", "pattern sql.lag(b:any_1, l:any_2, d:any_1, p:any_3, o:any_4):any_1 ", "SQLlag;", "return the value in the previous 'l' row in the partition or 'd' if non existent" ] diff --git a/clients/Tests/MAL-signatures.stable.out.int128 b/clients/Tests/MAL-signatures.stable.out.int128 --- a/clients/Tests/MAL-signatures.stable.out.int128 +++ b/clients/Tests/MAL-signatures.stable.out.int128 @@ -12695,6 +12695,9 @@ stdout of test 'MAL-signatures` in direc [ "batsql", "diff", "pattern batsql.diff(b:bat[:any_1]):bat[:bit] ", "SQLdiff;", "return true if cur != prev row" ] [ "batsql", "diff", "pattern batsql.diff(p:bat[:bit], b:bat[:any_1]):bat[:bit] ", "SQLdiff;", "return true if cur != prev row" ] [ "batsql", "first_value", "pattern batsql.first_value(b:bat[:any_1], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLfirst_value;", "return the first value of groups" ] +[ "batsql", "get_value", "pattern batsql.get_value(sname:bat[:str], sequence:str):bat[:lng] ", "mvc_bat_get_value;", "return the current value of the sequence" ] +[ "batsql", "get_value", "pattern batsql.get_value(sname:str, sequence:bat[:str]):bat[:lng] ", "mvc_bat_schema_sequences_get_value;", "return the current value of sequences" ] +[ "batsql", "get_value", "pattern batsql.get_value(sname:bat[:str], sequence:bat[:str]):bat[:lng] ", "mvc_bat_schemas_sequences_get_value;", "return the current value of sequences" ] [ "batsql", "lag", "pattern batsql.lag(b:bat[:any_1], l:any_2, d:any_1, p:any_3, o:any_4):bat[:any_1] ", "SQLlag;", "return the value in the previous 'l' row in the partition or 'd' if non existent" ] [ "batsql", "lag", "pattern batsql.lag(b:bat[:any_1], l:any_2, d:bat[:any_1], p:any_3, o:any_4):bat[:any_1] ", "SQLlag;", "return the value in the previous 'l' row in the partition or 'd' if non existent" ] [ "batsql", "lag", "pattern batsql.lag(b:bat[:any_1], l:any_2, p:any_3, o:any_4):bat[:any_1] ", "SQLlag;", "return the value in the previous 'l' row in the partition or NULL if non existent" ] @@ -12713,6 +12716,8 @@ stdout of test 'MAL-signatures` in direc [ "batsql", "max", "pattern batsql.max(b:bat[:any_1], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLmax;", "return the maximum of groups" ] [ "batsql", "min", "pattern batsql.min(b:bat[:any_1], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLmin;", "return the minimum of groups" ] [ "batsql", "next_value", "pattern batsql.next_value(sname:bat[:str], sequence:str):bat[:lng] ", "mvc_bat_next_value;", "return the next value of the sequence" ] +[ "batsql", "next_value", "pattern batsql.next_value(sname:str, sequence:bat[:str]):bat[:lng] ", "mvc_bat_schema_sequences_next_value;", "return the next value of sequences" ] +[ "batsql", "next_value", "pattern batsql.next_value(sname:bat[:str], sequence:bat[:str]):bat[:lng] ", "mvc_bat_schemas_sequences_next_value;", "return the next value of sequences" ] [ "batsql", "nth_value", "pattern batsql.nth_value(b:bat[:any_1], n:any_2, s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLnth_value;", "return the nth value of each group" ] [ "batsql", "nth_value", "pattern batsql.nth_value(b:bat[:any_1], n:bat[:any_2], s:bat[:lng], e:bat[:lng]):bat[:any_1] ", "SQLnth_value;", "return the nth value of each group" ] [ "batsql", "ntile", "pattern batsql.ntile(b:bat[:any_1], n:any_2, p:any_3, o:any_4):bat[:any_2] ", "SQLntile;", "return the groups divided as equally as possible" ] @@ -16072,11 +16077,12 @@ stdout of test 'MAL-signatures` in direc [ "sql", "export_table", "unsafe pattern sql.export_table(fname:str, fmt:str, colsep:str, recsep:str, qout:str, nullrep:str, onclient:int, tbl:bat[:str], attr:bat[:str], tpe:bat[:str], len:bat[:int], scale:bat[:int], cols:any...):int ", "mvc_export_row_wrap;", "Prepare a table result set for the COPY INTO stream" ] [ "sql", "export_table", "unsafe pattern sql.export_table(fname:str, fmt:str, colsep:str, recsep:str, qout:str, nullrep:str, onclient:int, tbl:bat[:str], attr:bat[:str], tpe:bat[:str], len:bat[:int], scale:bat[:int], cols:bat[:any]...):int ", "mvc_export_table_wrap;", "Prepare a table result set for the COPY INTO stream" ] [ "sql", "first_value", "pattern sql.first_value(b:any_1, s:lng, e:lng):any_1 ", "SQLfirst_value;", "return the first value of groups" ] -[ "sql", "flush_log", "command sql.flush_log():void ", "SQLflush_log;", "flush the log now" ] +[ "sql", "flush_log", "command sql.flush_log():void ", "SQLflush_log;", "start flushing the write ahead log" ] [ "sql", "getVariable", "pattern sql.getVariable(mvc:int, varname:str):any_1 ", "getVariable;", "Get the value of a session variable" ] [ "sql", "getVersion", "command sql.getVersion(clientid:int):lng ", "mvc_getVersion;", "Return the database version identifier for a client." ] [ "sql", "get_value", "pattern sql.get_value(sname:str, sequence:str):lng ", "mvc_get_value;", "return the current value of the sequence" ] [ "sql", "grow", "pattern sql.grow(tid:bat[:oid], X_0:any_1):int ", "mvc_grow_wrap;", "Resize the tid column of a declared table." ] +[ "sql", "hot_snapshot", "command sql.hot_snapshot(tarfile:str):void ", "SQLhot_snapshot;", "Write db snapshot to the given tar(.gz) file" ] [ "sql", "importTable", "unsafe pattern sql.importTable(sname:str, tname:str, onclient:int, fname:str...):bat[:any]... ", "mvc_bin_import_table_wrap;", "Import a table from the files (fname)" ] [ "sql", "include", "pattern sql.include(fname:str):void ", "SQLinclude;", "Compile and execute a sql statements on the file" ] [ "sql", "lag", "pattern sql.lag(b:any_1, l:any_2, d:any_1, p:any_3, o:any_4):any_1 ", "SQLlag;", "return the value in the previous 'l' row in the partition or 'd' if non existent" ] diff --git a/sql/backends/monet5/sql.c b/sql/backends/monet5/sql.c --- a/sql/backends/monet5/sql.c +++ b/sql/backends/monet5/sql.c @@ -754,6 +754,7 @@ mvc_next_value(Client cntxt, MalBlkPtr m mvc *m = NULL; str msg; sql_schema *s; + sql_sequence *seq; lng *res = getArgReference_lng(stk, pci, 0); const char *sname = *getArgReference_str(stk, pci, 1); const char *seqname = *getArgReference_str(stk, pci, 2); @@ -762,26 +763,51 @@ mvc_next_value(Client cntxt, MalBlkPtr m return msg; if ((msg = checkSQLContext(cntxt)) != NULL) return msg; - s = mvc_bind_schema(m, sname); - if (s) { - sql_sequence *seq = find_sql_sequence(s, seqname); - - if (seq && seq_next_value(seq, res)) { - m->last_id = *res; - stack_set_number(m, "last_id", m->last_id); - return MAL_SUCCEED; - } - } - throw(SQL, "sql.next_value", SQLSTATE(42000) "Error in fetching next value"); + if (!(s = mvc_bind_schema(m, sname))) + throw(SQL, "sql.next_value", SQLSTATE(3F000) "Cannot find the schema %s", sname); + if (!(seq = find_sql_sequence(s, seqname))) + throw(SQL, "sql.next_value", SQLSTATE(HY050) "Failed to fetch sequence %s.%s", sname, seqname); + + if (seq_next_value(seq, res)) { + m->last_id = *res; + stack_set_number(m, "last_id", m->last_id); + return MAL_SUCCEED; + } + throw(SQL, "sql.next_value", SQLSTATE(42000) "Error in fetching next value for sequence %s.%s", sname, seqname); } -/* str mvc_bat_next_value(bat *res, int *sid, str *seqname); */ +/* str mvc_get_value(lng *res, str *sname, str *seqname); */ str -mvc_bat_next_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +mvc_get_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { mvc *m = NULL; str msg; - BAT *b, *r; + sql_schema *s; + sql_sequence *seq; + lng *res = getArgReference_lng(stk, pci, 0); + const char *sname = *getArgReference_str(stk, pci, 1); + const char *seqname = *getArgReference_str(stk, pci, 2); + + if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL) + return msg; + if ((msg = checkSQLContext(cntxt)) != NULL) + return msg; + if (!(s = mvc_bind_schema(m, sname))) + throw(SQL, "sql.get_value", SQLSTATE(3F000) "Cannot find the schema %s", sname); + if (!(seq = find_sql_sequence(s, seqname))) + throw(SQL, "sql.get_value", SQLSTATE(HY050) "Failed to fetch sequence %s.%s", sname, seqname); + + if (seq_get_value(seq, res)) + return MAL_SUCCEED; + throw(SQL, "sql.get_value", SQLSTATE(42000) "Error in fetching current value for sequence %s.%s", sname, seqname); +} + +static str +mvc_bat_sequence_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int (*bulk_func)(seqbulk *, lng *), const char* call) +{ + mvc *m = NULL; + str msg = MAL_SUCCEED; + BAT *b = NULL, *r = NULL; BUN p, q; sql_schema *s = NULL; sql_sequence *seq = NULL; @@ -797,20 +823,15 @@ mvc_bat_next_value(Client cntxt, MalBlkP return msg; if ((b = BATdescriptor(sid)) == NULL) - throw(SQL, "sql.next_value", SQLSTATE(HY005) "Cannot access column descriptor"); - - r = COLnew(b->hseqbase, TYPE_lng, BATcount(b), TRANSIENT); - if (!r) { - BBPunfix(b->batCacheid); - throw(SQL, "sql.next_value", SQLSTATE(HY001) MAL_MALLOC_FAIL); - } - - if (!BATcount(b)) { - BBPunfix(b->batCacheid); - BBPkeepref(r->batCacheid); - *res = r->batCacheid; - return MAL_SUCCEED; - } + throw(SQL, call, SQLSTATE(HY005) "Cannot access column descriptor"); + + if (!(r = COLnew(b->hseqbase, TYPE_lng, BATcount(b), TRANSIENT))) { + msg = createException(SQL, call, SQLSTATE(HY001) MAL_MALLOC_FAIL); + goto bailout; + } + + if (!BATcount(b)) + goto bailout; /* Success case */ bi = bat_iterator(b); BATloop(b, p, q) { @@ -818,60 +839,222 @@ mvc_bat_next_value(Client cntxt, MalBlkP lng l; if (!s || strcmp(s->base.name, sname) != 0) { - if (sb) + if (sb) { seqbulk_destroy(sb); + sb = NULL; + } s = mvc_bind_schema(m, sname); seq = NULL; - if (!s || (seq = find_sql_sequence(s, seqname)) == NULL || !(sb = seqbulk_create(seq, BATcount(b)))) { - BBPunfix(b->batCacheid); - BBPunfix(r->batCacheid); - throw(SQL, "sql.next_value", SQLSTATE(HY050) "Cannot find the sequence %s.%s", sname,seqname); + if (!s || !(seq = find_sql_sequence(s, seqname)) || !(sb = seqbulk_create(seq, BATcount(b)))) { + msg = createException(SQL, call, SQLSTATE(HY050) "Cannot find the sequence %s.%s", sname, seqname); + goto bailout; } } - if (!seqbulk_next_value(sb, &l)) { - BBPunfix(b->batCacheid); - BBPunfix(r->batCacheid); - seqbulk_destroy(sb); - throw(SQL, "sql.next_value", SQLSTATE(HY050) "Cannot generate next sequence value %s.%s", sname, seqname); + if (!bulk_func(sb, &l)) { + msg = createException(SQL, call, SQLSTATE(HY050) "Cannot generate next sequence value %s.%s", sname, seqname); + goto bailout; } if (BUNappend(r, &l, false) != GDK_SUCCEED) { - BBPunfix(b->batCacheid); - BBPunfix(r->batCacheid); - seqbulk_destroy(sb); - throw(SQL, "sql.next_value", SQLSTATE(HY001) MAL_MALLOC_FAIL); + msg = createException(SQL, call, SQLSTATE(HY001) MAL_MALLOC_FAIL); + goto bailout; } } + +bailout: if (sb) seqbulk_destroy(sb); - BBPunfix(b->batCacheid); - BBPkeepref(r->batCacheid); - *res = r->batCacheid; - return MAL_SUCCEED; + if (b) + BBPunfix(b->batCacheid); + if (msg) + BBPreclaim(r); + else + BBPkeepref(*res = r->batCacheid); + return msg; } -/* str mvc_get_value(lng *res, str *sname, str *seqname); */ +str +mvc_bat_next_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + return mvc_bat_sequence_value(cntxt, mb, stk, pci, seqbulk_next_value, "sql.next_value"); +} + str -mvc_get_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +mvc_bat_get_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) +{ + return mvc_bat_sequence_value(cntxt, mb, stk, pci, seqbulk_get_value, "sql.get_value"); +} + +static str +mvc_bat_schema_sequences_value(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int (*bulk_func)(seqbulk *, lng *), const char* call) { mvc *m = NULL; - str msg; - sql_schema *s; - lng *res = getArgReference_lng(stk, pci, 0); + str msg = MAL_SUCCEED; + BAT *b = NULL, *r = NULL; + BUN p, q; + sql_schema *s = NULL; + sql_sequence *seq = NULL; + seqbulk *sb = NULL; + BATiter bi; + bat *res = getArgReference_bat(stk, pci, 0); const char *sname = *getArgReference_str(stk, pci, 1); - const char *seqname = *getArgReference_str(stk, pci, 2); + bat sid = *getArgReference_bat(stk, pci, 2); if ((msg = getSQLContext(cntxt, mb, &m, NULL)) != NULL) return msg; if ((msg = checkSQLContext(cntxt)) != NULL) return msg; - s = mvc_bind_schema(m, sname); - if (s) { - sql_sequence *seq = find_sql_sequence(s, seqname); - - if (seq && seq_get_value(seq, res)) - return MAL_SUCCEED; - } - throw(SQL, "sql.get_value", SQLSTATE(HY050) "Failed to fetch sequence %s.%s", sname, seqname); + + if ((b = BATdescriptor(sid)) == NULL) + throw(SQL, call, SQLSTATE(HY005) "Cannot access column descriptor"); + + if (!(r = COLnew(b->hseqbase, TYPE_lng, BATcount(b), TRANSIENT))) { + msg = createException(SQL, call, SQLSTATE(HY001) MAL_MALLOC_FAIL); + goto bailout; + } + + if (!(s = mvc_bind_schema(m, sname))) { + msg = createException(SQL, call, SQLSTATE(3F000) "Cannot find the schema %s", sname); + goto bailout; + } + + if (!BATcount(b)) + goto bailout; /* Success case */ + + bi = bat_iterator(b); + BATloop(b, p, q) { + str seqname = BUNtvar(bi, p); + lng l; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list