Changeset: ac8d1a9d4e51 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/ac8d1a9d4e51
Modified Files:
        sql/backends/monet5/rel_bin.c
        sql/backends/monet5/vaults/csv/csv.c
        sql/server/rel_basetable.c
        sql/server/rel_basetable.h
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_select.c
        sql/server/sql_parser.y
        sql/test/BugTracker-2011/Tests/time_precision.Bug-2873.test
        sql/test/miscellaneous/Tests/groupby_error.test
        sql/test/snodgrass/Tests/cast_select.test
        sql/test/snodgrass/Tests/date_parsing.test
Branch: default
Log Message:

time literals without precision now include parsing of the micro seconds
v1 of 3 level column references is added
select * from 'file' can now also be a compressed file (if compression is 
supported).


diffs (truncated from 365 to 300 lines):

diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c
--- a/sql/backends/monet5/rel_bin.c
+++ b/sql/backends/monet5/rel_bin.c
@@ -1321,20 +1321,20 @@ exp2bin_file_loader(backend *be, sql_exp
        assert(1 + list_length(type_list) == list_length(arg_list));
        */
 
+       sql_exp *eexp = arg_list->h->next->data;
+       assert(is_atom(eexp->type));
+       atom *ea = eexp->l;
+       assert(ea->data.vtype == TYPE_str);
+       char *ext = ea->data.val.sval;
+
+       file_loader_t *fl = fl_find(ext);
+       if (!fl)
+               return NULL;
        sql_exp *fexp = arg_list->h->data;
        assert(is_atom(fexp->type));
        atom *fa = fexp->l;
        assert(fa->data.vtype == TYPE_str);
        char *filename = fa->data.val.sval;
-
-       char *ext = strrchr(filename, '.');
-       if (ext)
-               ext = ext+1;
-       else
-               return NULL;
-       file_loader_t *fl = fl_find(ext);
-       if (!fl)
-               return NULL;
        return (stmt*)fl->load(be, f, filename);
 }
 
diff --git a/sql/backends/monet5/vaults/csv/csv.c 
b/sql/backends/monet5/vaults/csv/csv.c
--- a/sql/backends/monet5/vaults/csv/csv.c
+++ b/sql/backends/monet5/vaults/csv/csv.c
@@ -16,10 +16,10 @@
 
 #include <unistd.h>
 
-static FILE *
+static stream *
 csv_open_file(char* filename)
 {
-       return fopen(filename, "r");
+       return open_rastream(filename);
 }
 
 /* todo handle escapes */
@@ -360,7 +360,7 @@ typedef struct csv_t {
 static str
 csv_relation(mvc *sql, sql_subfunc *f, char *filename, list *res_exps, char 
*tname)
 {
-       FILE *file = csv_open_file(filename);
+       stream *file = csv_open_file(filename);
        char buf[8196+1];
 
        if(file == NULL)
@@ -371,8 +371,8 @@ csv_relation(mvc *sql, sql_subfunc *f, c
         * detect types
         * detect header
         */
-       ssize_t l = fread(buf, 1, 8196, file);
-       fclose(file);
+       ssize_t l = mnstr_read(file, buf, 1, 8196);
+       mnstr_close(file);
        if (l<0)
                return RUNTIME_LOAD_ERROR;
        buf[l] = 0;
diff --git a/sql/server/rel_basetable.c b/sql/server/rel_basetable.c
--- a/sql/server/rel_basetable.c
+++ b/sql/server/rel_basetable.c
@@ -228,6 +228,15 @@ rel_base_bind_column2( mvc *sql, sql_rel
        return bind_col(sql, rel, ba->name?ba->name:t->base.name, c);
 }
 
+sql_exp *
+rel_base_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char 
*tname, const char *cname)
+{
+       sql_table *t = rel->l;
+       if (!t->s || strcmp(t->s->base.name, sname) != 0)
+               return NULL;
+       return rel_base_bind_column2(sql, rel, tname, cname);
+}
+
 list *
 rel_base_projection( mvc *sql, sql_rel *rel, int intern)
 {
diff --git a/sql/server/rel_basetable.h b/sql/server/rel_basetable.h
--- a/sql/server/rel_basetable.h
+++ b/sql/server/rel_basetable.h
@@ -37,6 +37,7 @@ extern sql_rel *rel_base_bind_column_( s
 extern sql_exp *rel_base_bind_column( mvc *sql, sql_rel *rel, const char 
*cname, int no_tname);
 extern sql_rel *rel_base_bind_column2_( sql_rel *rel, const char *tname, const 
char *cname);
 extern sql_exp *rel_base_bind_column2( mvc *sql, sql_rel *rel, const char 
*tname, const char *cname);
+extern sql_exp *rel_base_bind_column3( mvc *sql, sql_rel *rel, const char 
*sname, const char *tname, const char *cname);
 
 extern list *rel_base_projection( mvc *sql, sql_rel *rel, int intern);
 extern list *rel_base_project_all( mvc *sql, sql_rel *rel, char *tname); /* 
select * from t */
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -445,6 +445,43 @@ rel_bind_column2( mvc *sql, sql_rel *rel
 }
 
 sql_exp *
+rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, const char 
*tname, const char *cname, int f)
+{
+       if (!sname)
+               return rel_bind_column2(sql, rel, tname, cname, f);
+       if (is_basetable(rel->op) && !rel->exps) {
+               return rel_base_bind_column3(sql, rel, sname, tname, cname);
+       } else if (is_set(rel->op)) {
+               return NULL;
+       } else if (is_project(rel->op) && rel->l) {
+               if (!is_processed(rel))
+                       return rel_bind_column3(sql, rel->l, sname, tname, 
cname, f);
+       } else if (is_join(rel->op)) {
+               sql_exp *e = rel_bind_column3(sql, rel->l, sname, tname, cname, 
f);
+
+               if (e && (is_right(rel->op) || is_full(rel->op)))
+                       set_has_nil(e);
+               if (!e) {
+                       e = rel_bind_column3(sql, rel->r, sname, tname, cname, 
f);
+                       if (e && (is_left(rel->op) || is_full(rel->op)))
+                               set_has_nil(e);
+               }
+               if (!e)
+                       return sql_error(sql, ERR_AMBIGUOUS, SQLSTATE(42000) 
"SELECT: identifier '%s.%s.%s' ambiguous", sname, tname, cname);
+               if (e)
+                       set_not_unique(e);
+               return e;
+       } else if (is_semi(rel->op) ||
+                  is_select(rel->op) ||
+                  is_topn(rel->op) ||
+                  is_sample(rel->op)) {
+               if (rel->l)
+                       return rel_bind_column3(sql, rel->l, sname, tname, 
cname, f);
+       }
+       return NULL;
+}
+
+sql_exp *
 rel_first_column(mvc *sql, sql_rel *r)
 {
        if (is_simple_project(r->op))
diff --git a/sql/server/rel_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -72,6 +72,7 @@ extern sql_rel *rel_select_copy(sql_allo
 
 extern sql_exp *rel_bind_column( mvc *sql, sql_rel *rel, const char *cname, 
int f, int no_tname);
 extern sql_exp *rel_bind_column2( mvc *sql, sql_rel *rel, const char *tname, 
const char *cname, int f );
+extern sql_exp *rel_bind_column3( mvc *sql, sql_rel *rel, const char *sname, 
const char *tname, const char *cname, int f );
 extern sql_exp *rel_first_column(mvc *sql, sql_rel *rel);
 
 extern sql_rel *rel_inplace_basetable(sql_rel *rel, sql_rel *bt);
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -524,27 +524,47 @@ nary_function_arg_types_2str(mvc *sql, l
 }
 
 static char *
-file_loader_add_table_column_types(mvc *sql, sql_subfunc *f, sql_exp *e, list 
*res_exps, char *tname)
+file_loader_add_table_column_types(mvc *sql, sql_subfunc *f, list *exps, list 
*res_exps, char *tname)
 {
-       if (!exp_is_atom(e))
+       sql_exp *file = exps->h->data;
+       if (!exp_is_atom(file))
                return "Filename missing";
-       atom *a = e->l;
+       atom *a = file->l;
        if (a->data.vtype != TYPE_str || !a->data.val.sval)
                return "Filename missing";
        char *filename = a->data.val.sval;
-       char *ext = strrchr(filename, '.');
+       char *ext = strrchr(filename, '.'), *ep = ext;
 
        if (ext) {
                ext=ext+1;
-               ext = toLower(ext);
+               ext = mkLower(sa_strdup(sql->sa, ext));
        }
 
        file_loader_t *fl = fl_find(ext);
-       if (!fl)
-               return sa_message(sql->ta, "extension '%s' missing", 
ext?ext:"");
+       if (!fl) {
+               /* maybe compressed */
+               char *p = ep - 1;
+               while (p > filename && *p != '.')
+                       p--;
+               if (p != filename) {
+                       ext = p + 1;
+                       ext = sa_strdup(sql->sa, ext);
+                       char *d = strchr(ext, '.');
+                       assert(d);
+                       *d = 0;
+                       fl = fl_find(ext);
+               }
+               if (!fl)
+                       return sa_message(sql->ta, "extension '%s' missing", 
ext?ext:"");
+       }
        str err = fl->add_types(sql, f, filename, res_exps, tname);
        if (err)
                return err;
+       sql_subtype *st = sql_bind_localtype("str");
+       sql_exp *ext_exp = exp_atom(sql->sa, atom_string(sql->sa, st, ext));
+       if (!ext_exp)
+                       return sql_error(sql, 02, SQLSTATE(HY013) 
MAL_MALLOC_FAIL);
+       append(exps, ext_exp);
        return NULL;
 }
 
@@ -559,8 +579,7 @@ rel_file_loader(mvc *sql, list *exps, li
                if (list_empty(tl) || f->func->vararg || (nexps = 
check_arguments_and_find_largest_any_type(sql, NULL, exps, f, 1))) {
                        list *res_exps = sa_list(sql->sa);
                        if (list_length(exps) == 1 && f && f->func->varres && 
strlen(f->func->mod) == 0 && strlen(f->func->imp) == 0) {
-                               sql_exp *file = exps->h->data;
-                               char *err = 
file_loader_add_table_column_types(sql, f, file, res_exps, tname);
+                               char *err = 
file_loader_add_table_column_types(sql, f, nexps, res_exps, tname);
                                if (err)
                                        return sql_error(sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SELECT: file_loader function type resolutions failed '%s'", 
err);
                        }
@@ -1299,29 +1318,35 @@ rel_column_ref(sql_query *query, sql_rel
                        return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) 
"SELECT: cannot use non GROUP BY column '%s' in query results without an 
aggregate function", name);
                if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && 
!is_freevar(exp))
                        exp = rel_groupby_add_aggr(sql, inner, exp);
-       } else if (dlist_length(l) == 2) {
+       } else if (dlist_length(l) == 2 || dlist_length(l) == 3) {
+               const char *sname = NULL;
                const char *tname = l->h->data.sval;
                const char *cname = l->h->next->data.sval;
+               if (dlist_length(l) == 3) {
+                       sname = l->h->data.sval;
+                       tname = l->h->next->data.sval;
+                       cname = l->h->next->next->data.sval;
+               }
 
                if (!exp && rel && inner)
-                       if (!(exp = rel_bind_column2(sql, inner, tname, cname, 
f)) && sql->session->status == -ERR_AMBIGUOUS)
+                       if (!(exp = rel_bind_column3(sql, inner, sname, tname, 
cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
                                return NULL;
                if (!exp && inner && is_sql_aggr(f) && (is_groupby(inner->op) 
|| is_select(inner->op))) {
                        /* if inner is selection, ie having clause, get the 
left relation to reach group by */
                        sql_rel *gp = inner;
                        while (gp && is_select(gp->op))
                                gp = gp->l;
-                       if (gp && gp->l && !(exp = rel_bind_column2(sql, gp->l, 
tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
+                       if (gp && gp->l && !(exp = rel_bind_column3(sql, gp->l, 
sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
                                return NULL;
                }
                if (!exp && query && query_has_outer(query)) {
                        int i;
 
                        for (i=query_has_outer(query)-1; i>= 0 && !exp && 
(outer = query_fetch_outer(query,i)); i--) {
-                               if (!(exp = rel_bind_column2(sql, outer, tname, 
cname, f | sql_outer)) && sql->session->status == -ERR_AMBIGUOUS)
+                               if (!(exp = rel_bind_column3(sql, outer, sname, 
tname, cname, f | sql_outer)) && sql->session->status == -ERR_AMBIGUOUS)
                                        return NULL;
                                if (!exp && is_groupby(outer->op)) {
-                                       if (!(exp = rel_bind_column2(sql, 
outer->l, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
+                                       if (!(exp = rel_bind_column3(sql, 
outer->l, sname, tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
                                                return NULL;
                                        else
                                                used_lower_after_processed = 
is_processed(outer);
@@ -1371,7 +1396,7 @@ rel_column_ref(sql_query *query, sql_rel
                                        *rel = rel_crossproduct(sql->sa, *rel, 
v, op_join);
                                else
                                        *rel = v;
-                               if (!(exp = rel_bind_column2(sql, *rel, tname, 
cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
+                               if (!(exp = rel_bind_column3(sql, *rel, sname, 
tname, cname, f)) && sql->session->status == -ERR_AMBIGUOUS)
                                        return NULL;
                        }
                }
@@ -1387,7 +1412,7 @@ rel_column_ref(sql_query *query, sql_rel
                        }
                }
                if (!exp) {
-                       if (inner && !is_sql_aggr(f) && is_groupby(inner->op) 
&& inner->l && (exp = rel_bind_column2(sql, inner->l, tname, cname, f)))
+                       if (inner && !is_sql_aggr(f) && is_groupby(inner->op) 
&& inner->l && (exp = rel_bind_column3(sql, inner->l, sname, tname, cname, f)))
                                return sql_error(sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s.%s' in query 
results without an aggregate function", tname, cname);
                }
 
@@ -1397,8 +1422,8 @@ rel_column_ref(sql_query *query, sql_rel
                        return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) 
"SELECT: cannot use non GROUP BY column '%s.%s' in query results without an 
aggregate function", tname, cname);
                if (exp && inner && is_groupby(inner->op) && !is_sql_aggr(f) && 
!is_freevar(exp))
                        exp = rel_groupby_add_aggr(sql, inner, exp);
-       } else if (dlist_length(l) >= 3) {
-               return sql_error(sql, 02, SQLSTATE(42000) "TODO: column names 
of level >= 3");
+       } else if (dlist_length(l) > 3) {
+               return sql_error(sql, 02, SQLSTATE(42000) "cross-database 
references are not implemented");
        }
        if (exp && !exp_is_atom(exp) && rel && !outer) {
                if (query->last_exp && query->last_rel == *rel && 
!is_sql_aggr(query->last_state) && is_sql_aggr(f)) {
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -5045,8 +5045,11 @@ literal:
                { sql_subtype t;
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to