Changeset: 73e6feaccc18 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=73e6feaccc18
Removed Files:
sql/test/BugTracker-2020/Tests/values-like-join.Bug-6954.stable.out.single
Modified Files:
sql/server/rel_dump.c
sql/server/rel_prop.c
sql/test/BugTracker-2009/Tests/copy_multiple_files.SF-2902320.stable.out
sql/test/BugTracker-2009/Tests/copy_multiple_files.SF-2902320.stable.out.Windows
sql/test/BugTracker-2009/Tests/use_order_column_first.SF-2686008.stable.out
sql/test/BugTracker-2010/Tests/LIMIT_OFFSET_big-endian.Bug-2622.stable.out
sql/test/BugTracker-2010/Tests/ORDER_BY_over_UNION_EXCEPT_INTERSECT.Bug-2606.stable.out
sql/test/BugTracker-2011/Tests/crash_on_alias.Bug-2798.stable.out
sql/test/BugTracker-2011/Tests/crash_on_alias.Bug-2798.stable.out.int128
sql/test/BugTracker-2013/Tests/rangejoin_optimizer.Bug-3411.stable.out
sql/test/BugTracker-2015/Tests/crash.Bug-3736.stable.out
sql/test/BugTracker-2015/Tests/crash_in_reduce_groupby.Bug-3818.stable.out
sql/test/BugTracker-2015/Tests/large_join.Bug-3809.stable.out
sql/test/BugTracker-2015/Tests/quantile_function_resolution.Bug-3773.stable.out
sql/test/BugTracker-2015/Tests/schema_view.Bug-3708.stable.out
sql/test/BugTracker-2016/Tests/memory-consumption-query-PLAN-25joins.Bug-3972.stable.out
sql/test/BugTracker-2016/Tests/merge_project.Bug-3955.stable.out
sql/test/BugTracker-2017/Tests/caching_stats_bug.6374.stable.out
sql/test/BugTracker-2017/Tests/sqlitelogictest-aggregation-having-avg.Bug-6428.stable.out
sql/test/BugTracker-2018/Tests/count_from_commented_function_signatures.Bug-6542.stable.out
sql/test/BugTracker-2018/Tests/local_replica_table_not_detected.Bug-6620.stable.out
sql/test/BugTracker-2020/Tests/table-udf-on-remote.Bug-6971.py
sql/test/BugTracker-2020/Tests/table-udf-on-remote.Bug-6971.stable.out
sql/test/BugTracker-2020/Tests/values-like-join.Bug-6954.sql
sql/test/BugTracker-2020/Tests/values-like-join.Bug-6954.stable.out
sql/test/BugTracker/Tests/jdbc_no_debug.SF-1739356.stable.out
sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-0join-query.stable.out
sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-0join-view.stable.out
sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-query.stable.out
sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-1join-view.stable.out
sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-2join-query.stable.out
sql/test/FeatureRequests/Tests/foreign_key_outer_join_dead_code_elimination-plan-2join-view.stable.out
sql/test/Tests/keys.stable.out
sql/test/Tests/order_by_complex_exp.stable.out
sql/test/Tests/truncate-statements-extra.stable.out
sql/test/astro/Tests/update.stable.out
sql/test/merge-partitions/Tests/mergepart31.stable.out
sql/test/mergetables/Tests/mergequery.stable.out
sql/test/mergetables/Tests/part-elim.stable.out
sql/test/miscellaneous/Tests/groupby_error.stable.out
sql/test/miscellaneous/Tests/groupby_expressions.stable.out
sql/test/miscellaneous/Tests/simple_plans.stable.out
sql/test/out2in/Tests/out2in.stable.out.int128
Branch: Oct2020
Log Message:
Show identifiers between double quotes in the SQL plan and escape them properly
on remote plan parsing. I will do the merge into default. I know the plans
changed
diffs (truncated from 4089 to 300 lines):
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
@@ -75,6 +75,25 @@ cmp_print(mvc *sql, stream *fout, int cm
mnstr_printf(fout, " %s ", r);
}
+static const char *
+dump_escape_ident(sql_allocator *sa, const char *s)
+{
+ char *res = NULL;
+ if (s) {
+ size_t l = strlen(s);
+ char *r = SA_NEW_ARRAY(sa, char, (l * 2) + 1);
+
+ res = r;
+ while (*s) {
+ if (*s == '"')
+ *r++ = '\\';
+ *r++ = *s++;
+ }
+ *r = '\0';
+ }
+ return res;
+}
+
static void exps_print(mvc *sql, stream *fout, list *exps, int depth, list
*refs, int alias, int brackets);
static void
@@ -90,8 +109,8 @@ exp_print(mvc *sql, stream *fout, sql_ex
const char *rname = exp_relname(e);
int level = GET_PSM_LEVEL(e->flag);
if (rname)
- mnstr_printf(fout, "\"%s\".", rname);
- mnstr_printf(fout, "\"%s\" = ", exp_name(e));
+ mnstr_printf(fout, "\"%s\".",
dump_escape_ident(sql->ta, rname));
+ mnstr_printf(fout, "\"%s\" = ",
dump_escape_ident(sql->ta, exp_name(e)));
exp_print(sql, fout, e->l, depth, refs, 0, 0);
mnstr_printf(fout, " FRAME %d ", level);
alias = 0;
@@ -102,8 +121,8 @@ exp_print(mvc *sql, stream *fout, sql_ex
int level = GET_PSM_LEVEL(e->flag);
mnstr_printf(fout, "declare ");
if (rname)
- mnstr_printf(fout, "\"%s\".", rname);
- mnstr_printf(fout, "\"%s\" %s FRAME %d ", exp_name(e),
type_str ? type_str : "", level);
+ mnstr_printf(fout, "\"%s\".",
dump_escape_ident(sql->ta, rname));
+ mnstr_printf(fout, "\"%s\" %s FRAME %d ",
dump_escape_ident(sql->ta, exp_name(e)), type_str ? type_str : "", level);
alias = 0;
} else if (e->flag & PSM_RETURN) {
int level = GET_PSM_LEVEL(e->flag);
@@ -142,11 +161,11 @@ exp_print(mvc *sql, stream *fout, sql_ex
atom *a = e->l;
if (atom_type(a)->type->localtype == TYPE_ptr) {
sql_table *t = a->data.val.pval;
- mnstr_printf(fout, "%s(%s)",
+ mnstr_printf(fout, "%s(\"%s\")",
isStream(t)?"stream":
isMergeTable(t)?"merge table":
isReplicaTable(t)?"replica
table":"table",
- t->base.name);
+ dump_escape_ident(sql->ta,
t->base.name));
} else {
char *t = sql_subtype_string(sql->ta,
atom_type(a));
if (a->isnull)
@@ -164,8 +183,8 @@ exp_print(mvc *sql, stream *fout, sql_ex
if (e->r) { /* named parameters and declared variables
*/
sql_var_name *vname = (sql_var_name*) e->r;
if (vname->sname)
- mnstr_printf(fout, "\"%s\".",
vname->sname);
- mnstr_printf(fout, "\"%s\"", vname->name);
+ mnstr_printf(fout, "\"%s\".",
dump_escape_ident(sql->ta, vname->sname));
+ mnstr_printf(fout, "\"%s\"",
dump_escape_ident(sql->ta, vname->name));
} else if (e->f) { /* values list */
list *l = e->f;
exps_print(sql, fout, l, depth, refs, 0, 0);
@@ -176,9 +195,9 @@ exp_print(mvc *sql, stream *fout, sql_ex
} break;
case e_func: {
sql_subfunc *f = e->f;
- mnstr_printf(fout, "%s.%s",
- f->func->s?f->func->s->base.name:"sys",
- f->func->base.name);
+ mnstr_printf(fout, "\"%s\".\"%s\"",
+ f->func->s?dump_escape_ident(sql->ta,
f->func->s->base.name):"sys",
+ dump_escape_ident(sql->ta, f->func->base.name));
exps_print(sql, fout, e->l, depth, refs, alias, 1);
if (e->r) { /* list of optional lists */
list *l = e->r;
@@ -190,9 +209,9 @@ exp_print(mvc *sql, stream *fout, sql_ex
} break;
case e_aggr: {
sql_subfunc *a = e->f;
- mnstr_printf(fout, "%s.%s",
- a->func->s?a->func->s->base.name:"sys",
- a->func->base.name);
+ mnstr_printf(fout, "\"%s\".\"%s\"",
+ a->func->s?dump_escape_ident(sql->ta,
a->func->s->base.name):"sys",
+ dump_escape_ident(sql->ta, a->func->base.name));
if (need_distinct(e))
mnstr_printf(fout, " unique ");
if (need_no_nil(e))
@@ -208,8 +227,8 @@ exp_print(mvc *sql, stream *fout, sql_ex
if (is_freevar(e))
mnstr_printf(fout, "!!!FREE!!! ");
if (e->l)
- mnstr_printf(fout, "\"%s\".", (char*)e->l);
- mnstr_printf(fout, "\"%s\"", (char*)e->r);
+ mnstr_printf(fout, "\"%s\".",
dump_escape_ident(sql->ta, (char*)e->l));
+ mnstr_printf(fout, "\"%s\"", dump_escape_ident(sql->ta,
(char*)e->r));
if (exp_relname(e) && exp_name(e) && e->l && e->r &&
strcmp(exp_relname(e), e->l) == 0 &&
strcmp(exp_name(e), e->r) == 0)
@@ -236,7 +255,7 @@ exp_print(mvc *sql, stream *fout, sql_ex
exps_print(sql, fout, e->l, depth, refs, alias, 1);
if (is_anti(e))
mnstr_printf(fout, " !");
- mnstr_printf(fout, " FILTER %s ", f->func->base.name);
+ mnstr_printf(fout, " FILTER \"%s\" ",
dump_escape_ident(sql->ta, f->func->base.name));
exps_print(sql, fout, e->r, depth, refs, alias, 1);
} else if (e->f) {
exp_print(sql, fout, e->r, depth+1, refs, 0, 0);
@@ -288,8 +307,8 @@ exp_print(mvc *sql, stream *fout, sql_ex
if (exp_name(e) && alias) {
mnstr_printf(fout, " as ");
if (exp_relname(e))
- mnstr_printf(fout, "\"%s\".", exp_relname(e));
- mnstr_printf(fout, "\"%s\"", exp_name(e));
+ mnstr_printf(fout, "\"%s\".",
dump_escape_ident(sql->ta, exp_relname(e)));
+ mnstr_printf(fout, "\"%s\"", dump_escape_ident(sql->ta,
exp_name(e)));
}
if (comma)
mnstr_printf(fout, ", ");
@@ -393,7 +412,8 @@ rel_print_(mvc *sql, stream *fout, sql_
sql_column *c = rel->r;
if (!t && c) {
- mnstr_printf(fout, "dict(%s.%s)", c->t->base.name,
c->base.name);
+ mnstr_printf(fout, "dict(\"%s\".\"%s\")",
+ dump_escape_ident(sql->ta,
c->t->base.name), dump_escape_ident(sql->ta, c->base.name));
} else {
const char *sname = t->s ? t->s->base.name : NULL; /*
All tables, but declared ones on the stack have schema */
const char *tname = t->base.name;
@@ -405,17 +425,17 @@ rel_print_(mvc *sql, stream *fout, sql_
tname = mapiuri_table( uri, sql->sa, tname);
}
if (sname)
- mnstr_printf(fout, "%s(%s.%s)",
+ mnstr_printf(fout, "%s(\"%s\".\"%s\")",
isStream(t)?"stream":
isRemote(t)&&decorate?"REMOTE":
isReplicaTable(t)?"REPLICA":"table",
- sname, tname);
+ dump_escape_ident(sql->ta, sname),
dump_escape_ident(sql->ta, tname));
else
- mnstr_printf(fout, "%s(%s)",
+ mnstr_printf(fout, "%s(\"%s\")",
isStream(t)?"stream":
isRemote(t)&&decorate?"REMOTE":
isReplicaTable(t)?"REPLICA":"table",
- tname);
+ dump_escape_ident(sql->ta, tname));
}
if (rel->exps)
exps_print(sql, fout, rel->exps, depth, refs, 1, 0);
@@ -690,15 +710,33 @@ skipIdent( char *r, int *pos)
{
if (r[*pos] == '"') {
(*pos)++;
- while(r[*pos] && r[*pos] != '"')
- (*pos)++;
- (*pos)++;
+ while(r[*pos] && r[*pos] != '"') {
+ if (r[*pos] == '\\' && r[*pos + 1] == '"') /* We send
escaped '"' character, so consider this pair as just one */
+ (*pos)+=2;
+ else
+ (*pos)++;
+ }
} else {
while(r[*pos] && (isalnum((unsigned char) r[*pos]) || r[*pos]
== '_' || r[*pos] == '%'))
(*pos)++;
}
}
+static void /* We send escaped '"' character, so remove the escape after
parsing */
+convertIdent(char *r)
+{
+ int i = 0, j = 0;
+ while(r[i] && r[i] != '"') {
+ if (r[i] == '\\' && r[i + 1] == '"') {
+ r[j++] = '"';
+ i+=2;
+ } else {
+ r[j++] = r[i++];
+ }
+ }
+ r[i] = '\0';
+}
+
static void
skipIdentOrSymbol( char *r, int *pos)
{
@@ -756,30 +794,31 @@ read_prop( mvc *sql, sql_exp *exp, char
{
/* PROPs */
if (strncmp(r+*pos, "JOINIDX", strlen("JOINIDX")) == 0) {
- int old;
- char *sname,*iname;
+ char *sname, *tname, *iname;
sql_schema *s = NULL;
prop *p;
(*pos)+= (int) strlen("JOINIDX");
skipWS(r, pos);
/* schema.table.index */
- sname = r+*pos;
+ sname = r+*pos + 1;
skipIdent(r,pos);
+ convertIdent(sname);
+ (*pos)++;
if (r[*pos] != '.')
return sql_error(sql, -1, SQLSTATE(42000) "JOINIDX:
missing '.'\n");
- r[*pos] = 0;
+ tname = r+*pos + 1;
+ skipIdent(r,pos);
+ convertIdent(tname);
(*pos)++;
- skipIdent(r,pos);
if (r[*pos] != '.')
return sql_error(sql, -1, SQLSTATE(42000) "JOINIDX:
missing '.'\n");
- r[*pos] = 0;
- (*pos)++;
- iname = r+*pos;
+ iname = r+*pos + 1;
skipIdent(r,pos);
- old = r[*pos];
- r[*pos] = 0;
+ convertIdent(iname);
+ (*pos)++;
+ (void) tname;
s = mvc_bind_schema(sql, sname);
if (sname && !s)
return sql_error(sql, -1, SQLSTATE(42000) "Schema %s
missing\n", sname);
@@ -788,7 +827,6 @@ read_prop( mvc *sql, sql_exp *exp, char
if (!(p->value = mvc_bind_idx(sql, s, iname)))
return sql_error(sql, -1, SQLSTATE(42000)
"Index %s missing\n", iname);
}
- r[*pos] = old;
skipWS(r,pos);
}
return exp;
@@ -850,17 +888,24 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
quote = (r[*pos] == '"');
b += quote;
skipIdent(r, pos);
- e = r+*pos-quote;
+ e = r+*pos;
+ (*pos) += quote;
skipWS(r, pos);
switch(r[*pos]) {
case '.':
*e = 0;
(*pos)++;
tname = b;
+ convertIdent(tname);
cname = r + *pos + quote;
skipIdentOrSymbol(r, pos);
- e = r+*pos - quote;
- old = *e;
+ e = r+*pos;
+ if (quote) {
+ old = ' ';
+ convertIdent(cname);
+ } else {
+ old = *e;
+ }
*e = 0;
tname = sa_strdup(sql->sa, tname);
@@ -905,11 +950,10 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
}
skipWS(r, pos);
if (filter) {
- fname = r+*pos;
+ fname = r+*pos + 1;
skipIdent(r,pos);
- e = r+*pos;
- *e = 0;
+ convertIdent(fname);
(*pos)++;
skipWS(r,pos);
}
@@ -960,6 +1004,7 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
return sql_error(sql, -1,
SQLSTATE(42000) "Type: missing ')'\n");
(*pos)++;
}
+ convertIdent(tname);
if (!(tpe = sql_bind_subtype(sql->sa, tname, d, s)))
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list