Changeset: 86c7c5885d83 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=86c7c5885d83
Modified Files:
sql/server/rel_exp.h
sql/test/miscellaneous/Tests/simple_selects.sql
sql/test/miscellaneous/Tests/simple_selects.stable.out
tools/merovingian/daemon/controlrunner.c
Branch: default
Log Message:
Merge with octbugs branch.
diffs (truncated from 7341 to 300 lines):
diff --git a/documentation/source/build.rst b/documentation/source/build.rst
--- a/documentation/source/build.rst
+++ b/documentation/source/build.rst
@@ -31,7 +31,7 @@ Prerequisites
=============
PATH settings: None
-ROle of clients?? How to install
+Role of clients?? How to install
## Testing
@@ -47,9 +47,9 @@ Configuration options
The way options interact with building of the MonetDB source has
fundamentally changed from the way this was done using the autotools
-buildsystem. Now almost all options are on by default. And these options
+build system. Now almost all options are on by default. And these options
mostly control library detection. In the old system, it was possible to
-build a subset of the codebase. For example, you could choose not to
+build a subset of the code base. For example, you could choose not to
build the sql part. Now the every part of the code is build, as long as
the dependent libraries are detected. And by default, the system would
try to detect all dependent libraries. If your system does not have a
diff --git a/monetdb5/mal/mal_linker.c b/monetdb5/mal/mal_linker.c
--- a/monetdb5/mal/mal_linker.c
+++ b/monetdb5/mal/mal_linker.c
@@ -485,7 +485,7 @@ MSP_locate_sqlscript(const char *filenam
int
malLibraryEnabled(str name)
{
- if (strcmp(name, "pyapi3") == 0) {
+ if (strcmp(name, "pyapi3") == 0 || strcmp(name, "pyapi3map") == 0) {
const char *val = GDKgetenv("embedded_py");
return val && (strcmp(val, "3") == 0 ||
strcasecmp(val, "true") == 0 ||
@@ -510,7 +510,7 @@ malLibraryEnabled(str name)
char *
malLibraryHowToEnable(str name)
{
- if (strcmp(name, "pyapi3") == 0) {
+ if (strcmp(name, "pyapi3") == 0 || strcmp(name, "pyapi3map") == 0) {
HOW_TO_ENABLE_ERROR("Python 3", "embedded_py=3")
} else if (strcmp(name, "rapi") == 0) {
HOW_TO_ENABLE_ERROR("R", "embedded_r=true")
diff --git a/monetdb5/modules/kernel/bat5.c b/monetdb5/modules/kernel/bat5.c
--- a/monetdb5/modules/kernel/bat5.c
+++ b/monetdb5/modules/kernel/bat5.c
@@ -867,8 +867,7 @@ BKCshrinkBAT(bat *ret, const bat *bid, c
bn->tseqbase = oid_nil;
bn->tkey = b->tkey;
bn->tnonil = b->tnonil;
- bn->tnil = b->tnil;
-
+ bn->tnil = false; /* can't be sure if values deleted */
BBPunfix(b->batCacheid);
BBPunfix(bs->batCacheid);
diff --git a/monetdb5/modules/mal/batcalc.c b/monetdb5/modules/mal/batcalc.c
--- a/monetdb5/modules/mal/batcalc.c
+++ b/monetdb5/modules/mal/batcalc.c
@@ -1051,8 +1051,7 @@ CMDconvertbat(MalStkPtr stk, InstrPtr pc
}
if (s && ATOMtype(s->ttype) != TYPE_oid) {
BBPunfix(b->batCacheid);
- if (s)
- BBPunfix(s->batCacheid);
+ BBPunfix(s->batCacheid);
throw(MAL, "batcalc.convert", SQLSTATE(42000)
ILLEGAL_ARGUMENT);
}
}
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -1564,32 +1564,126 @@ rel_read(mvc *sql, char *r, int *pos, li
skipIdent(r, pos);
e = r+*pos;
skipWS(r, pos);
- if (r[*pos] != ')')
- sql_error(sql, -1, SQLSTATE(42000) "Table:
missing ')'\n");
- *e = 0;
- (*pos)++;
- skipWS(r, pos);
- if (!(s = mvc_bind_schema(sql, sname)))
- return sql_error(sql, -1, SQLSTATE(3F000) "No
such schema '%s'\n", sname);
- if (!(t = mvc_bind_table(sql, s, tname)))
- return sql_error(sql, -1, SQLSTATE(42S02)
"Table missing '%s.%s'\n", sname, tname);
- if (isMergeTable(t))
- return sql_error(sql, -1, SQLSTATE(42000)
"Merge tables not supported under remote connections\n");
- if (isRemote(t))
- return sql_error(sql, -1, SQLSTATE(42000)
"Remote tables not supported under remote connections\n");
- if (isReplicaTable(t))
- return sql_error(sql, -1, SQLSTATE(42000)
"Replica tables not supported under remote connections\n");
- rel = rel_basetable(sql, t, tname);
- if (!table_privs(sql, t, PRIV_SELECT) && !(rel =
rel_reduce_on_column_privileges(sql, rel, t)))
- return sql_error(sql, -1, SQLSTATE(42000)
"Access denied for %s to table '%s.%s'\n",
sqlvar_get_string(find_global_var(sql, mvc_bind_schema(sql, "sys"),
"current_user")), s->base.name, tname);
+ if (r[*pos] == '(') { /* table returning function */
+ node *m;
+ sql_exp *tudf, *next;
+ list *inputs, *outputs;
+ sql_subfunc *sf;
+ int x = *pos, y; /* save current position,
after parsing the input relation we have to parse the input parameters */
+ bool inside_identifier = false;
+
+ while (r[*pos] && (inside_identifier || r[*pos]
!= '\n')) { /* the input parameters must be parsed after the input relation,
skip them for now */
+ (*pos)++;
+ if (r[*pos] == '"')
+ inside_identifier =
!inside_identifier;
+ }
+ if (r[*pos] != '\n')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing ']' for output
parameters\n");
+
+ skipWS(r, pos); /* now parse the input relation
*/
+ if (!(lrel = rel_read(sql, r, pos, refs)))
+ return NULL;
+ y = *pos; /* later we have to return here to
parse the output identifiers */
+ *pos = x;
+ if (!(inputs = read_exps(sql, lrel, NULL, NULL,
r, pos, '(', 0)))
+ return NULL;
+
+ if (!(s = mvc_bind_schema(sql, sname)))
+ return sql_error(sql, -1,
SQLSTATE(3F000) "No such schema '%s'\n", sname);
+ *e = 0; /* closing table udf name string */
+ if (!(tudf = find_table_function(sql, s, tname,
list_empty(inputs) ? NULL : inputs, list_empty(inputs) ? NULL :
exp_types(sql->sa, inputs))))
+ return sql_error(sql, 02,
SQLSTATE(42S02) "No such table returning function '%s.%s'\n", sname, tname);
+ sf = tudf->f;
+ if (tudf->type != e_func || sf->func->type !=
F_UNION)
+ return sql_error(sql, 02,
SQLSTATE(42000) "'%s' does not return a table\n", exp_func_name(tudf));
+
+ *pos = y; /* now at the end of the input
relation */
+ skipWS(r, pos);
+ if (r[*pos] != ')')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing ')' at the end of the input
relation\n");
+ (*pos)++;
+ skipWS(r, pos);
+
+ /* Parse identifiers manually, we cannot use
read_exps because the labels may not match */
+ if (r[*pos] != '[')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing '[' for output
parameters\n");
+ (*pos)++;
+ skipWS(r, pos);
+ m = sf->func->res->h;
+ outputs = new_exp_list(sql->sa);
+ while (r[*pos] && r[*pos] != ']' && m) {
+ sql_arg *a = m->data;
+ char *nrname, *ncname;
- if (!r[*pos])
- return rel;
+ if (r[*pos] != '"')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing identifier for output
parameters\n");
+ (*pos)++;
+ nrname = r+*pos;
+ skipIdent(r, pos);
+ if (r[*pos] != '"')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing identifier for output
parameters\n");
+ e = r+*pos;
+ *e = 0;
+ (*pos)++;
+ if (r[*pos] != '.')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing '.' for output
parameters\n");
+ (*pos)++; /* skip '.' */
+ if (r[*pos] != '"')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing identifier for output
parameters\n");
+ (*pos)++;
+ ncname = r+*pos;
+ skipIdent(r, pos);
+ if (r[*pos] != '"')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing identifier for output
parameters\n");
+ e = r+*pos;
+ *e = 0;
+ (*pos)++;
+ if (r[*pos] == ',')
+ (*pos)++;
- /* scan aliases */
- if (!(exps = read_exps(sql, rel, NULL, NULL, r, pos,
'[', 0)))
- return NULL;
- rel->exps = exps;
+ next = exp_column(sql->sa, nrname,
ncname, &a->type, CARD_MULTI, 1, 0);
+ set_basecol(next);
+ append(outputs, next);
+ m = m->next;
+ skipWS(r, pos);
+ }
+ if (r[*pos] != ']')
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: missing ']' for output
parameters\n");
+ (*pos)++;
+ skipWS(r, pos);
+ if (list_length(outputs) !=
list_length(sf->func->res))
+ return sql_error(sql, -1,
SQLSTATE(42000) "Table returning function: the number of output parameters
don't match the table ones relation outputs: %d != function outputs: %d\n",
+
list_length(outputs), list_length(sf->func->res));
+ rel = rel_table_func(sql->sa, lrel, tudf,
outputs, TABLE_FROM_RELATION);
+ } else {
+ if (r[*pos] != ')')
+ sql_error(sql, -1, SQLSTATE(42000)
"Table: missing ')'\n");
+ *e = 0;
+ (*pos)++;
+ skipWS(r, pos);
+ if (!(s = mvc_bind_schema(sql, sname)))
+ return sql_error(sql, -1,
SQLSTATE(3F000) "No such schema '%s'\n", sname);
+ if (!(t = mvc_bind_table(sql, s, tname)))
+ return sql_error(sql, -1,
SQLSTATE(42S02) "Table missing '%s.%s'\n", sname, tname);
+ if (isMergeTable(t))
+ return sql_error(sql, -1,
SQLSTATE(42000) "Merge tables not supported under remote connections\n");
+ if (isRemote(t))
+ return sql_error(sql, -1,
SQLSTATE(42000) "Remote tables not supported under remote connections\n");
+ if (isReplicaTable(t))
+ return sql_error(sql, -1,
SQLSTATE(42000) "Replica tables not supported under remote connections\n");
+ rel = rel_basetable(sql, t, tname);
+ if (!table_privs(sql, t, PRIV_SELECT) && !(rel
= rel_reduce_on_column_privileges(sql, rel, t)))
+ return sql_error(sql, -1,
SQLSTATE(42000) "Access denied for %s to table '%s.%s'\n",
+
sqlvar_get_string(find_global_var(sql, mvc_bind_schema(sql, "sys"),
"current_user")), s->base.name, tname);
+
+ if (!r[*pos])
+ return rel;
+
+ /* scan aliases */
+ if (!(exps = read_exps(sql, rel, NULL, NULL, r,
pos, '[', 0)))
+ return NULL;
+ rel->exps = exps;
+ }
if (strncmp(r+*pos, "COUNT", strlen("COUNT")) == 0) {
(*pos)+= (int) strlen("COUNT");
skipWS( r, pos);
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -1091,15 +1091,20 @@ exp_cmp( sql_exp *e1, sql_exp *e2)
return (e1 == e2)?0:-1;
}
+#define alias_cmp(e1, e2) \
+ do { \
+ if (e1->alias.rname && e2->alias.rname &&
strcmp(e1->alias.rname, e2->alias.rname) == 0) \
+ return strcmp(e1->alias.name, e2->alias.name); \
+ if (!e1->alias.rname && !e2->alias.rname && e1->alias.label ==
e2->alias.label && e1->alias.name && e2->alias.name) \
+ return strcmp(e1->alias.name, e2->alias.name); \
+ } while (0);
+
int
exp_equal( sql_exp *e1, sql_exp *e2)
{
if (e1 == e2)
return 0;
- if (e1->alias.rname && e2->alias.rname && strcmp(e1->alias.rname,
e2->alias.rname) == 0)
- return strcmp(e1->alias.name, e2->alias.name);
- if (!e1->alias.rname && !e2->alias.rname && e1->alias.label ==
e2->alias.label && e1->alias.name && e2->alias.name)
- return strcmp(e1->alias.name, e2->alias.name);
+ alias_cmp(e1, e2);
return -1;
}
@@ -1288,6 +1293,10 @@ exp_match_exp( sql_exp *e1, sql_exp *e2)
{
if (exp_match(e1, e2))
return 1;
+ if (is_ascending(e1) != is_ascending(e2) || nulls_last(e1) !=
nulls_last(e2) || zero_if_empty(e1) != zero_if_empty(e2) ||
+ need_no_nil(e1) != need_no_nil(e2) || is_anti(e1) !=
is_anti(e2) || is_semantics(e1) != is_semantics(e2) ||
+ need_distinct(e1) != need_distinct(e2))
+ return 0;
if (e1->type == e2->type) {
switch(e1->type) {
case e_cmp:
@@ -1300,7 +1309,7 @@ exp_match_exp( sql_exp *e1, sql_exp *e2)
exp_match_list(e1->l, e2->l) &&
exp_match_list(e1->r, e2->r))
return 1;
- else if (e1->flag == e2->flag && is_anti(e1) ==
is_anti(e2) &&
+ else if (e1->flag == e2->flag &&
(e1->flag == cmp_in || e1->flag == cmp_notin) &&
exp_match_exp(e1->l, e2->l) &&
exp_match_list(e1->r, e2->r))
@@ -1357,6 +1366,27 @@ exps_any_match(list *l, sql_exp *e)
}
static int
+exp_no_alias(sql_exp *e1, sql_exp *e2)
+{
+ alias_cmp(e1, e2);
+ /* at least one of the expressions don't have an alias, so there's a
match */
+ return 0;
+}
+
+sql_exp *
+exps_any_match_same_or_no_alias(list *l, sql_exp *e)
+{
+ if (!l)
+ return NULL;
+ for (node *n = l->h; n ; n = n->next) {
+ sql_exp *ne = (sql_exp *) n->data;
+ if ((exp_match(ne, e) || exp_refers(ne, e) || exp_match_exp(ne,
e)) && exp_no_alias(e, ne) == 0)
+ return ne;
+ }
+ return NULL;
+}
+
+static int
exps_are_joins( list *l )
{
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list