Changeset: bf888184fc89 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=bf888184fc89 Modified Files: sql/server/rel_dump.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-2011/Tests/crash_on_alias.Bug-2798.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/miscellaneous/Tests/groupby_error.stable.out sql/test/miscellaneous/Tests/groupby_prepare.stable.out sql/test/miscellaneous/Tests/simple_plans.stable.out sql/test/out2in/Tests/out2in.stable.out Branch: default Log Message:
Merged with Oct2020 diffs (truncated from 3606 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,10 +161,10 @@ 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\")", 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) @@ -163,8 +182,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); @@ -175,9 +194,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; @@ -189,9 +208,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)) @@ -207,8 +226,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) @@ -235,7 +254,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); @@ -287,8 +306,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, ", "); @@ -392,7 +411,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; @@ -404,15 +424,15 @@ 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\")", 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\")", 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); @@ -687,15 +707,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) { @@ -734,8 +772,12 @@ readString( char *r, int *pos) if (r[*pos] == '"'){ (*pos)++; st = r+*pos; - while (r[*pos] != '"') - (*pos)++; + while (r[*pos] != '"') { + if (r[*pos] == '\\' && r[*pos + 1] == '"') + (*pos)+=2; + else + (*pos)++; + } r[*pos] = 0; (*pos)++; } @@ -749,30 +791,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); @@ -781,7 +824,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; @@ -843,17 +885,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); @@ -898,11 +947,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); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list