Changeset: 68194b8b85bf for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/68194b8b85bf
Branch: default
Log Message:
Merge with Dec2025 branch.
diffs (truncated from 591 to 300 lines):
diff --git a/clients/mapiclient/mhelp.c b/clients/mapiclient/mhelp.c
--- a/clients/mapiclient/mhelp.c
+++ b/clients/mapiclient/mhelp.c
@@ -412,12 +412,15 @@ SQLhelp sqlhelp1[] = {
{"EXPLAIN",
"Display logical or physical execution plan for the SQL statement.",
"EXPLAIN [BEFORE|AFTER] [step] [SHOW DETAILS] statement\n"
- "\twhere step is REL_UNNEST|REL_REWRITE|PHYSICAL",
+ "\twhere step is LOGICAL UNNEST | LOGICAL REWRITE [posint] [posint] |
PHYSICAL",
NULL,
"Plain EXPLAIN defaults to logical plan.\n"
- "Use REL_UNNEST|REL_REWRITE|PHYSICAL to specify compilation step to
show.\n"
+ "Use LOGICAL UNNEST|LOGICAL REWRITE|PHYSICAL to specify compilation
step to show.\n"
"Use BEFORE|AFTER to specify moment of compilation step to output.\n"
"The default is AFTER.\n"
+ "Two positive numbers can be passed to LOGICAL REWRITE to stop at
specific\n"
+ "rewriter index or rewrite loop cycle, respectively.\n"
+ "If only one positive number is passed to LOGICAL REWRITE, rewrite
stop cycle defaults to 0.\n"
"SHOW DETAILS displays column properties, rewriter number of changes\n"
"and time spent.\n"
"See also
https://www.monetdb.org/documentation/admin-guide/debugging-features/explain-sql-stmt/"},
diff --git a/common/stream/bs.c b/common/stream/bs.c
--- a/common/stream/bs.c
+++ b/common/stream/bs.c
@@ -30,6 +30,11 @@ bs_create(void)
if ((ns = malloc(sizeof(*ns))) == NULL)
return NULL;
*ns = (bs) {0};
+#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
+ InitializeCriticalSection(&ns->lock);
+#else
+ pthread_mutex_init(&ns->lock, NULL);
+#endif
return ns;
}
@@ -178,16 +183,28 @@ bs_putoob(stream *ss, char val)
static int
bs_getoob(stream *ss)
{
+ int oobval;
bs *s = (bs *) ss->stream_data.p;
if (s == NULL || ss->inner->getoob == NULL)
return 0;
+#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
+ EnterCriticalSection(&s->lock);
+#else
+ pthread_mutex_lock(&s->lock);
+#endif
if (s->seenoob) {
s->seenoob = false;
- return s->oobval;
- }
- if (ss->readonly && s->itotal == 0)
- return ss->inner->getoob(ss->inner);
- return 0;
+ oobval = s->oobval;
+ } else if (ss->readonly && s->itotal == 0)
+ oobval = ss->inner->getoob(ss->inner);
+ else
+ oobval = 0;
+#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
+ LeaveCriticalSection(&s->lock);
+#else
+ pthread_mutex_unlock(&s->lock);
+#endif
+ return oobval;
}
/* Read buffered data and return the number of items read. At the
@@ -306,6 +323,11 @@ bs_destroy(stream *ss)
if (s) {
if (ss->inner)
ss->inner->destroy(ss->inner);
+#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
+ DeleteCriticalSection(&s->lock);
+#else
+ pthread_mutex_destroy(&s->lock);
+#endif
free(s);
}
destroy_stream(ss);
diff --git a/common/stream/socket_stream.c b/common/stream/socket_stream.c
--- a/common/stream/socket_stream.c
+++ b/common/stream/socket_stream.c
@@ -92,7 +92,7 @@ socket_getoob(stream *s)
}
}
#endif
- char b = 0;
+ unsigned char b = 0;
switch (recv(fd, &b, 1, MSG_OOB)) {
case 0:
/* unexpectedly didn't receive a byte */
@@ -163,7 +163,7 @@ socket_getoob_unix(stream *s)
if (nr == 2 && buf[0] == OOBMSG0 && buf[1] == OOBMSG1) {
nr = recv(fd, buf, 3, 0);
if (nr == 3)
- return buf[2];
+ return (unsigned char) buf[2];
}
}
return 0;
diff --git a/common/stream/stream_internal.h b/common/stream/stream_internal.h
--- a/common/stream/stream_internal.h
+++ b/common/stream/stream_internal.h
@@ -62,6 +62,9 @@
#include <lz4.h>
#include <lz4frame.h>
#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
#ifndef SHUT_RD
#define SHUT_RD 0
@@ -259,11 +262,16 @@ stream *open_lz4wastream(const char *res
* bs2.c should be dropped.*/
typedef struct bs bs;
struct bs {
+#if !defined(HAVE_PTHREAD_H) && defined(WIN32)
+ CRITICAL_SECTION lock;
+#else
+ pthread_mutex_t lock;
+#endif
uint16_t nr; /* how far we got in buf */
uint16_t itotal; /* amount available in current read block */
bool seenflush;
bool seenoob;
- char oobval;
+ unsigned char oobval;
int64_t blks; /* read/written blocks (possibly partial) */
int64_t bytes; /* read/written bytes */
char buf[BLOCK]; /* the buffered data (minus the size of
diff --git a/sql/ChangeLog.Dec2025 b/sql/ChangeLog.Dec2025
--- a/sql/ChangeLog.Dec2025
+++ b/sql/ChangeLog.Dec2025
@@ -34,12 +34,13 @@
guaranteed.
* Fri Oct 3 2025 Lucas Pereira <[email protected]>
-- EXPLAIN now supports a BEFORE/AFTER REL_UNNEST/REL_REWRITE/PHYSICAL
+- EXPLAIN now supports a BEFORE/AFTER LOGICAL UNNEST/LOGICAL REWRITE/PHYSICAL
clause to indicate which phase of query compilation to show. A plain
- EXPLAIN is equivalent to EXPLAIN BEFORE PHYSICAL, which is what PLAN
- used to do. The old EXPLAIN is now EXPLAIN PHYSICAL. SHOW DETAILS
- includes more information about properties, rewriters number of
- changes and time spent.
+ EXPLAIN is equivalent to EXPLAIN AFTER REWRITE, which is what PLAN
+ used to do. The old EXPLAIN is now EXPLAIN PHYSICAL. LOGICAL REWRITE also
+ supports specifying two positive values, rewriter index number and
+ optimizer loop cycle stop counter. SHOW DETAILS includes more information
+ about properties, rewriters number of changes and time spent.
- The PLAN keyword has been removed.
* Tue Sep 16 2025 Sjoerd Mullender <[email protected]>
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
@@ -138,7 +138,7 @@ sql_symbol2relation(backend *be, symbol
sql_rel *rel;
sql_query *query = query_create(be->mvc);
int value_based_opt = be->mvc->emode != m_prepare, storage_based_opt;
- int profile = be->mvc->emode == m_plan;
+ int profile = be->mvc->emode == m_explain;
rel = rel_semantic(query, sym);
@@ -5623,8 +5623,6 @@ SQLread_dump_rel(Client cntxt, MalBlkPtr
if (refs == NULL)
goto bailout;
- m->step = S_REL_REWRITE;
- m->temporal = T_AFTER;
m->show_details = true;
rel_print_refs(m, s, rel, 0, refs, 0);
diff --git a/sql/backends/monet5/sql_execute.c
b/sql/backends/monet5/sql_execute.c
--- a/sql/backends/monet5/sql_execute.c
+++ b/sql/backends/monet5/sql_execute.c
@@ -61,7 +61,7 @@ SQLrun(Client c, backend *be)
TRC_INFO(SQL_EXECUTION, "Executing: %s", c->query);
MT_thread_setworking(c->query);
- if (m->emod == mod_explain) {
+ if (m->emod == mod_explain_phys) {
if (c->curprg->def)
printFunction(c->fdout, mb, 0, LIST_MAL_NAME |
LIST_MAL_VALUE | LIST_MAL_TYPE | LIST_MAL_MAPI);
} else {
diff --git a/sql/backends/monet5/sql_gencode.c
b/sql/backends/monet5/sql_gencode.c
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -988,7 +988,7 @@ sql_relation2stmt(backend *be, sql_rel *
sql_error(c, 003, SQLSTATE(42000) "Missing relation to convert
into statements");
return NULL;
} else {
- if (c->emode == m_plan) {
+ if (c->emode == m_explain) {
rel_print(c, r, 0);
} else {
s = output_rel_bin(be, r, top);
diff --git a/sql/backends/monet5/sql_scenario.c
b/sql/backends/monet5/sql_scenario.c
--- a/sql/backends/monet5/sql_scenario.c
+++ b/sql/backends/monet5/sql_scenario.c
@@ -1423,6 +1423,8 @@ SQLparser_body(Client c, backend *be)
m->temporal = T_NONE;
m->step = S_NONE;
m->show_details = false;
+ m->rewriter_stop_idx = -1;
+ m->rewriter_stop_cycle = -1;
m->trace = false;
c->query = NULL;
c->qryctx.starttime = GDKusec();
@@ -1552,7 +1554,9 @@ SQLparser_body(Client c, backend *be)
opt = ((m->emod == mod_exec) == 0); /* no need
to optimize prepare - execute */
}
- if (be->mvc->emod == mod_explain && be->mvc->step ==
S_PHYSICAL && be->mvc->temporal == T_BEFORE)
+ if (be->mvc->emod == mod_explain_phys &&
+ be->mvc->step == S_PHYSICAL &&
+ be->mvc->temporal == T_BEFORE)
opt = 0;
if (err)
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -621,9 +621,21 @@ run_optimizer_set(visitor *v, sql_optimi
run->name = set[i].name;
int changes = v->changes;
lng clk = GDKusec();
+
+ if (BEFORE_LOGICAL_REWRITE(v->sql) &&
+ v->sql->rewriter_stop_idx >= 0 &&
+ set[i].index ==
v->sql->rewriter_stop_idx)
+ return rel;
+
rel = opt(v, gp, rel);
run->time += (GDKusec() - clk);
run->nchanges += (v->changes - changes);
+
+ if (AFTER_LOGICAL_REWRITE(v->sql) &&
+ v->sql->rewriter_stop_idx >= 0 &&
+ set[i].index ==
v->sql->rewriter_stop_idx)
+ return rel;
+
} else {
rel = opt(v, gp, rel);
}
@@ -637,38 +649,64 @@ run_optimizer_set(visitor *v, sql_optimi
static sql_rel *
rel_optimizer_one(mvc *sql, sql_rel *rel, int profile, int instantiate, int
value_based_opt, int storage_based_opt)
{
- global_props gp = {.cnt = {0}, .instantiate = (uint8_t)instantiate,
.opt_cycle = 0 };
- visitor v = { .sql = sql, .value_based_opt = value_based_opt,
.storage_based_opt = storage_based_opt, .changes = 1, .data = &gp };
+ global_props gp = {
+ .cnt = {0},
+ .instantiate = (uint8_t)instantiate,
+ .opt_cycle = 0
+ };
+
+ visitor v = {
+ .sql = sql,
+ .value_based_opt = value_based_opt,
+ .storage_based_opt = storage_based_opt,
+ .changes = 1,
+ .data = &gp
+ };
- sql->runs = !(ATOMIC_GET(&GDKdebug) & TESTINGMASK) && profile ?
ma_zalloc(sql->sa, NSQLREWRITERS * sizeof(sql_optimizer_run)) : NULL;
- for ( ;rel && gp.opt_cycle < 20 && v.changes; gp.opt_cycle++) {
+ sql->runs = !(ATOMIC_GET(&GDKdebug) & TESTINGMASK) && profile ?
+ ma_zalloc(sql->sa, NSQLREWRITERS * sizeof(sql_optimizer_run)) :
+ NULL;
+
+ for ( ; rel && gp.opt_cycle < 20 && v.changes; gp.opt_cycle++) {
v.changes = 0;
- gp = (global_props) {.cnt = {0}, .instantiate =
(uint8_t)instantiate, .opt_cycle = gp.opt_cycle};
- rel = rel_visitor_topdown(&v, rel, &rel_properties); /* collect
relational tree properties */
+ gp = (global_props) {
+ .cnt = {0},
+ .instantiate = (uint8_t)instantiate,
+ .opt_cycle = gp.opt_cycle
+ };
+ /* collect relational tree properties */
+ rel = rel_visitor_topdown(&v, rel, &rel_properties);
gp.opt_level = calculate_opt_level(sql, rel);
if (gp.opt_level == 0 && !gp.needs_mergetable_rewrite)
break;
sql->recursive = gp.recursive;
rel = run_optimizer_set(&v, sql->runs, rel, &gp,
pre_sql_optimizers);
+
+ if (sql->step == S_LOGICAL_REWRITE &&
+ sql->rewriter_stop_cycle >= 0 &&
+ gp.opt_cycle == sql->rewriter_stop_cycle)
+ return rel;
}
+
#ifndef NDEBUG
assert(gp.opt_cycle < 20);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]