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]