Changeset: 4ae287228851 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4ae287228851 Added Files: sql/test/Tests/appendtwice.sql sql/test/Tests/appendtwice.stable.err sql/test/Tests/appendtwice.stable.out Modified Files: monetdb5/optimizer/opt_parappend.c sql/test/Tests/All Branch: copybinary Log Message:
Keep subsequent append to the same table separate diffs (160 lines): diff --git a/monetdb5/optimizer/opt_parappend.c b/monetdb5/optimizer/opt_parappend.c --- a/monetdb5/optimizer/opt_parappend.c +++ b/monetdb5/optimizer/opt_parappend.c @@ -72,7 +72,7 @@ OPTparappendImplementation(Client cntxt, pushInstruction(mb, p); } if (msg != MAL_SUCCEED) - return msg; + goto end; } assert(state.prep_stmt == NULL); @@ -125,6 +125,7 @@ transform(parstate *state, Client cntxt, if (!sname_constant || !tname_constant || !cname_constant) { // cannot transform this + flush_finish_stmt(state, mb); pushInstruction(mb, old); return MAL_SUCCEED; } @@ -132,6 +133,7 @@ transform(parstate *state, Client cntxt, const char *cname = getVarConstant(mb, cname_var).val.sval; if (cname[0] == '%') { // don't touch indices + flush_finish_stmt(state, mb); pushInstruction(mb, old); return MAL_SUCCEED; } @@ -168,44 +170,46 @@ setup_append_prep(parstate *state, Clien // check if the state refers to a sql.append_prep statement that can be // reused. - InstrPtr prep_stmt = NULL; + InstrPtr prep_stmt = state->prep_stmt; do { - if (state->prep_stmt == NULL) + if (prep_stmt == NULL) break; - InstrPtr prev = state->prep_stmt; - - int existing_sname_var = getArg(prev, prev->retc + 1); - int existing_tname_var = getArg(prev, prev->retc + 2); + int existing_sname_var = getArg(prep_stmt, prep_stmt->retc + 1); + int existing_tname_var = getArg(prep_stmt, prep_stmt->retc + 2); const char *existing_sname = getVarConstant(mb, existing_sname_var).val.sval; const char *incoming_sname = getVarConstant(mb, sname_var).val.sval; - if (strcmp(existing_sname, incoming_sname) != 0) + if (strcmp(existing_sname, incoming_sname) != 0) { + prep_stmt = NULL; break; + } const char *existing_tname = getVarConstant(mb, existing_tname_var).val.sval; const char *incoming_tname = getVarConstant(mb, tname_var).val.sval; - if (strcmp(existing_tname, incoming_tname) != 0) + if (strcmp(existing_tname, incoming_tname) != 0) { + prep_stmt = NULL; break; + } const char *incoming_cname = getVarConstant(mb, cname_var).val.sval; - int existing_cols = prev->retc - 1; - for (int i = prev->argc - existing_cols; i < prev->argc; i++) { - int var = getArg(prev, i); + int existing_cols = prep_stmt->retc - 1; + for (int i = prep_stmt->argc - existing_cols; i < prep_stmt->argc; i++) { + int var = getArg(prep_stmt, i); const char *existing_cname = getVarConstant(mb, var).val.sval; if (strcmp(existing_cname, incoming_cname) == 0) { // We're not prepared for the complications that may arise // when there are multiple appends to the same column. - // In particular we would have to track down where the previous + // In particular we would have to track down where the prep_stmtious // cookie is used and make sure we execute the next append // after that use. // This is unlikely to occur in practice, so instead we just start over. + prep_stmt = NULL; break; } } // It seems there is no objection to reusing the existing sql.append_prep. - prep_stmt = prev; } while (0); int cookie_var = newTmpVariable(mb, TYPE_ptr); diff --git a/sql/test/Tests/All b/sql/test/Tests/All --- a/sql/test/Tests/All +++ b/sql/test/Tests/All @@ -128,3 +128,5 @@ HAVE_PYMONETDB&HAVE_LIBBZ2?hot_snapshot_ HAVE_PYMONETDB&HAVE_LIBLZMA?hot_snapshot_xz HAVE_PYTHON_LZ4&HAVE_PYMONETDB&HAVE_LIBLZ4?hot_snapshot_lz4 !HAVE_PYTHON_LZ4&HAVE_PYMONETDB&HAVE_LIBLZ4?hot_snapshot_lz4_lite + +appendtwice diff --git a/sql/test/Tests/appendtwice.sql b/sql/test/Tests/appendtwice.sql new file mode 100644 --- /dev/null +++ b/sql/test/Tests/appendtwice.sql @@ -0,0 +1,10 @@ + +DROP TABLE IF EXISTS foo CASCADE; +CREATE TABLE foo(i INT, j INT DEFAULT 42); + +CREATE PROCEDURE append_twice() BEGIN INSERT INTO foo(i) VALUES (0), (1), (2); INSERT INTO foo(i) VALUES (10), (11), (12); END; + +-- if optimizer.parappend does not keep the appends separate, data may get lost +CALL append_twice(); + +SELECT * FROM foo; diff --git a/sql/test/Tests/appendtwice.stable.err b/sql/test/Tests/appendtwice.stable.err new file mode 100644 --- /dev/null +++ b/sql/test/Tests/appendtwice.stable.err @@ -0,0 +1,12 @@ +stderr of test 'appendtwice` in directory 'sql/test` itself: + + +# 14:57:08 > +# 14:57:08 > "mclient" "-lsql" "-ftest" "-tnone" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-11017" "--port=36169" +# 14:57:08 > + + +# 14:57:08 > +# 14:57:08 > "Done." +# 14:57:08 > + diff --git a/sql/test/Tests/appendtwice.stable.out b/sql/test/Tests/appendtwice.stable.out new file mode 100644 --- /dev/null +++ b/sql/test/Tests/appendtwice.stable.out @@ -0,0 +1,26 @@ +stdout of test 'appendtwice` in directory 'sql/test` itself: + + +# 14:57:08 > +# 14:57:08 > "mclient" "-lsql" "-ftest" "-tnone" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-11017" "--port=36169" +# 14:57:08 > + +#DROP TABLE IF EXISTS foo CASCADE; +#CREATE TABLE foo(i INT, j INT DEFAULT 42); +#CREATE PROCEDURE append_twice() BEGIN INSERT INTO foo(i) VALUES (0), (1), (2); INSERT INTO foo(i) VALUES (10), (11), (12); END; +#SELECT * FROM foo; +% sys.foo, sys.foo # table_name +% i, j # name +% int, int # type +% 2, 2 # length +[ 0, 42 ] +[ 1, 42 ] +[ 2, 42 ] +[ 10, 42 ] +[ 11, 42 ] +[ 12, 42 ] + +# 14:57:08 > +# 14:57:08 > "Done." +# 14:57:08 > + _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list