Changeset: 10001fd9ddc5 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/10001fd9ddc5 Modified Files: sql/server/sqlparse.c Branch: clean_parser Log Message:
initial printing added to sqlparse diffs (224 lines): diff --git a/sql/server/sqlparse.c b/sql/server/sqlparse.c --- a/sql/server/sqlparse.c +++ b/sql/server/sqlparse.c @@ -127,6 +127,205 @@ mvc_new( bstream *rs, stream *ws) { return m; } +char * +qname_schema(dlist *qname) +{ + assert(qname && qname->h); + + if (dlist_length(qname) == 2) { + return qname->h->data.sval; + } else if (dlist_length(qname) == 3) { + return qname->h->next->data.sval; + } + return NULL; +} + +char * +qname_schema_object(dlist *qname) +{ + assert(qname && qname->h); + + if (dlist_length(qname) == 1) { + return qname->h->data.sval; + } else if (dlist_length(qname) == 2) { + return qname->h->next->data.sval; + } else if (dlist_length(qname) == 3) { + return qname->h->next->next->data.sval; + } + return "unknown"; +} + + +static char * sp_symbol2string(mvc *sql, symbol *se, int expression, char **err); + +static char * +dlist2string(mvc *sql, dlist *l, int expression, char **err) +{ + char *b = NULL; + dnode *n; + + for (n=l->h; n; n = n->next) { + char *s = NULL; + + if (n->type == type_string && n->data.sval) + s = sa_strdup(sql->ta, n->data.sval); + else if (n->type == type_symbol) + s = sp_symbol2string(sql, n->data.sym, expression, err); + + if (!s) + return NULL; + if (b) { + char *o = SA_NEW_ARRAY(sql->ta, char, strlen(b) + strlen(s) + 2); + if (o) + stpcpy(stpcpy(stpcpy(o, b), "."), s); + b = o; + if (b == NULL) + return NULL; + } else { + b = s; + } + } + return b; +} + +static const char * +symbol_escape_ident(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; +} + +char * +sp_symbol2string(mvc *sql, symbol *se, int expression, char **err) +{ + /* inner sp_symbol2string uses the temporary allocator */ + switch (se->token) { + case SQL_NOP: { + dnode *lst = se->data.lval->h, *ops = NULL, *aux; + const char *op = symbol_escape_ident(sql->ta, qname_schema_object(lst->data.lval)), + *sname = symbol_escape_ident(sql->ta, qname_schema(lst->data.lval)); + int i = 0, nargs = 0; + char** inputs = NULL, *res; + size_t inputs_length = 0, extra = sname ? strlen(sname) + 3 : 0; + + if (lst->next->next->data.lval) + ops = lst->next->next->data.lval->h; + + for (aux = ops; aux; aux = aux->next) + nargs++; + if (!(inputs = SA_ZNEW_ARRAY(sql->ta, char*, nargs))) + return NULL; + + for (aux = ops; aux; aux = aux->next) { + if (!(inputs[i] = sp_symbol2string(sql, aux->data.sym, expression, err))) { + return NULL; + } + inputs_length += strlen(inputs[i]); + i++; + } + + if ((res = SA_NEW_ARRAY(sql->ta, char, extra + strlen(op) + inputs_length + 3 + (nargs - 1 /* commas */) + 2))) { + char *concat = res; + if (sname) + concat = stpcpy(stpcpy(stpcpy(res, "\""), sname), "\"."); + concat = stpcpy(stpcpy(stpcpy(concat, "\""), op), "\"("); + i = 0; + for (aux = ops; aux; aux = aux->next) { + concat = stpcpy(concat, inputs[i]); + if (aux->next) + concat = stpcpy(concat, ","); + i++; + } + concat = stpcpy(concat, ")"); + } + return res; + } + case SQL_PARAMETER: + return sa_strdup(sql->ta, "?"); + case SQL_NULL: + return sa_strdup(sql->ta, "NULL"); + case SQL_ATOM:{ + AtomNode *an = (AtomNode *) se; + if (an && an->a) + return atom2sql(sql->ta, an->a, sql->timezone); + else + return sa_strdup(sql->ta, "NULL"); + } + case SQL_NEXT: { + const char *seq = symbol_escape_ident(sql->ta, qname_schema_object(se->data.lval)), + *sname = qname_schema(se->data.lval); + char *res; + + if (!sname) + sname = sql->session->schema->base.name; + sname = symbol_escape_ident(sql->ta, sname); + + if ((res = SA_NEW_ARRAY(sql->ta, char, strlen("next value for \"") + strlen(sname) + strlen(seq) + 5))) + stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "next value for \""), sname), "\".\""), seq), "\""); + return res; + } break; + case SQL_IDENT: + case SQL_COLUMN: { + /* can only be variables */ + dlist *l = se->data.lval; + assert(l->h->type != type_lng); + if (expression && dlist_length(l) == 1 && l->h->type == type_string) { + /* when compiling an expression, a column of a table might be present in the symbol, so we need this case */ + const char *op = symbol_escape_ident(sql->ta, l->h->data.sval); + char *res; + + if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(op) + 3))) + stpcpy(stpcpy(stpcpy(res, "\""), op), "\""); + return res; + } else if (expression && dlist_length(l) == 2 && l->h->type == type_string && l->h->next->type == type_string) { + const char *first = symbol_escape_ident(sql->ta, l->h->data.sval), + *second = symbol_escape_ident(sql->ta, l->h->next->data.sval); + char *res; + + if (!first || !second) + return NULL; + if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(first) + strlen(second) + 6))) + stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "\""), first), "\".\""), second), "\""); + return res; + } else { + char *e = dlist2string(sql, l, expression, err); + if (e) + *err = e; + return NULL; + } + } + case SQL_CAST: { + dlist *dl = se->data.lval; + char *val = NULL, *tpe = NULL, *res; + + if (!(val = sp_symbol2string(sql, dl->h->data.sym, expression, err)) || !(tpe = subtype2string2(sql->ta, &dl->h->next->data.typeval))) + return NULL; + if ((res = SA_NEW_ARRAY(sql->ta, char, strlen(val) + strlen(tpe) + 11))) + stpcpy(stpcpy(stpcpy(stpcpy(stpcpy(res, "cast("), val), " as "), tpe), ")"); + return res; + } + default: { + const char msg[] = "SQL feature not yet available for expressions and default values: "; + char *tok_str = token2string(se->token); + if ((*err = SA_NEW_ARRAY(sql->ta, char, strlen(msg) + strlen(tok_str) + 1))) + stpcpy(stpcpy(*err, msg), tok_str); + } + } + return NULL; +} + int main(int argc, char *argv[]) { @@ -155,7 +354,13 @@ main(int argc, char *argv[]) return -4; while ((err = sqlparse(m)) == 0 && m->scanner.rs->pos < m->scanner.rs->len) { if (m->sym) { - printf("parsed\n"); + char *err = NULL; + char *res = sp_symbol2string(m, m->sym, 1, &err); + + if (err) + printf("ERROR: %s\n", err); + else + printf("SYM: %s\n", res); } scanner_query_processed(&m->scanner); m->sym = NULL; _______________________________________________ checkin-list mailing list -- checkin-list@monetdb.org To unsubscribe send an email to checkin-list-le...@monetdb.org