Changeset: 1cb74d115c00 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=1cb74d115c00 Removed Files: sql/test/rdf/Tests/q8_v_small.reqtests sql/test/rdf/Tests/q8_v_small.sql sql/test/rdf/Tests/q8_v_small.stable.err sql/test/rdf/Tests/q8_v_small.stable.out Modified Files: monetdb5/modules/mal/mkey.c monetdb5/modules/mal/pcre.c sql/server/rel_rel.h sql/server/rel_select.c sql/server/rel_updates.c sql/server/sql_atom.c sql/server/sql_semantic.c sql/test/BugTracker-2009/Tests/AVG_of_SQRT.SF-2757642.timeout sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.sql sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.err sql/test/BugTracker-2015/Tests/window_function_crash.Bug-3861.stable.out sql/test/merge-partitions/Tests/mergepart20.sql sql/test/merge-partitions/Tests/mergepart20.stable.out sql/test/miscellaneous/Tests/simple_selects.sql sql/test/miscellaneous/Tests/simple_selects.stable.out sql/test/rdf/Tests/All sql/test/rdf/Tests/q8_v.stable.err sql/test/rdf/Tests/q8_v.stable.out sql/test/rdf/Tests/q8_v.timeout sql/test/subquery/Tests/correlated.stable.err sql/test/subquery/Tests/subquery.sql sql/test/subquery/Tests/subquery.stable.err sql/test/subquery/Tests/subquery.stable.out sql/test/subquery/Tests/subquery3.sql sql/test/subquery/Tests/subquery3.stable.err sql/test/subquery/Tests/subquery3.stable.out sql/test/subquery/Tests/subquery4.sql sql/test/subquery/Tests/subquery4.stable.err sql/test/subquery/Tests/subquery4.stable.out Branch: default Log Message:
Merged with linear-hashing diffs (truncated from 2627 to 300 lines): diff --git a/monetdb5/modules/mal/mkey.c b/monetdb5/modules/mal/mkey.c --- a/monetdb5/modules/mal/mkey.c +++ b/monetdb5/modules/mal/mkey.c @@ -51,6 +51,8 @@ MKEYhash(Client cntxt, MalBlkPtr mb, Mal val= getArgReference(stk,p,1); switch (ATOMstorage(tpe)) { case TYPE_void: + *res = lng_nil; /* It can be called from SQL */ + break; case TYPE_bat: case TYPE_ptr: // illegal types, avoid falling into the default case. diff --git a/monetdb5/modules/mal/pcre.c b/monetdb5/modules/mal/pcre.c --- a/monetdb5/modules/mal/pcre.c +++ b/monetdb5/modules/mal/pcre.c @@ -1542,7 +1542,6 @@ PCREindex(int *res, const pcre *pattern, #endif } - str PCREpatindex(int *ret, const str *pat, const str *val) { @@ -1550,6 +1549,11 @@ PCREpatindex(int *ret, const str *pat, c pcre *re = NULL; char *ppat = NULL, *msg; + if (strNil(*pat) || strNil(*val)) { + *ret = int_nil; + return MAL_SUCCEED; + } + if ((msg = pat2pcre(&ppat, *pat)) != MAL_SUCCEED) return msg; if ((msg = pcre_compile_wrap(&re, ppat, FALSE)) != MAL_SUCCEED) { @@ -1591,7 +1595,6 @@ PCREquote(str *ret, const str *val) return MAL_SUCCEED; } - str PCREsql2pcre(str *ret, const str *pat, const str *esc) { 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 @@ -13,31 +13,35 @@ #include "sql_relation.h" #include "sql_semantic.h" -#define sql_from 1 -#define sql_where 2 -#define sql_sel 4 -#define sql_having 8 -#define sql_orderby 16 -#define sql_groupby 32 //ORed -#define sql_aggr 64 //ORed -#define sql_farg 128 //ORed -#define sql_window 256 //ORed -#define sql_join 512 //ORed -#define sql_outer 1024 //ORed -#define sql_group_totals 2048 //ORed +#define sql_from (1 << 0) +#define sql_where (1 << 1) +#define sql_sel (1 << 2) +#define sql_having (1 << 3) +#define sql_orderby (1 << 4) +#define sql_groupby (1 << 5) //ORed +#define sql_aggr (1 << 6) //ORed +#define sql_farg (1 << 7) //ORed +#define sql_window (1 << 8) //ORed +#define sql_join (1 << 9) //ORed +#define sql_outer (1 << 10) //ORed +#define sql_group_totals (1 << 11) //ORed +#define sql_update_set (1 << 12) //ORed +#define sql_update_where (1 << 13) //ORed -#define is_sql_from(X) ((X & sql_from) == sql_from) -#define is_sql_where(X) ((X & sql_where) == sql_where) -#define is_sql_sel(X) ((X & sql_sel) == sql_sel) -#define is_sql_having(X) ((X & sql_having) == sql_having) -#define is_sql_orderby(X) ((X & sql_orderby) == sql_orderby) -#define is_sql_groupby(X) ((X & sql_groupby) == sql_groupby) -#define is_sql_aggr(X) ((X & sql_aggr) == sql_aggr) -#define is_sql_farg(X) ((X & sql_farg) == sql_farg) -#define is_sql_window(X) ((X & sql_window) == sql_window) -#define is_sql_join(X) ((X & sql_join) == sql_join) -#define is_sql_outer(X) ((X & sql_outer) == sql_outer) +#define is_sql_from(X) ((X & sql_from) == sql_from) +#define is_sql_where(X) ((X & sql_where) == sql_where) +#define is_sql_sel(X) ((X & sql_sel) == sql_sel) +#define is_sql_having(X) ((X & sql_having) == sql_having) +#define is_sql_orderby(X) ((X & sql_orderby) == sql_orderby) +#define is_sql_groupby(X) ((X & sql_groupby) == sql_groupby) +#define is_sql_aggr(X) ((X & sql_aggr) == sql_aggr) +#define is_sql_farg(X) ((X & sql_farg) == sql_farg) +#define is_sql_window(X) ((X & sql_window) == sql_window) +#define is_sql_join(X) ((X & sql_join) == sql_join) +#define is_sql_outer(X) ((X & sql_outer) == sql_outer) #define is_sql_group_totals(X) ((X & sql_group_totals) == sql_group_totals) +#define is_sql_update_set(X) ((X & sql_update_set) == sql_update_set) +#define is_sql_update_where(X) ((X & sql_update_where) == sql_update_where) #define is_updateble(rel) \ (rel->op == op_basetable || \ 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 @@ -3246,6 +3246,13 @@ static sql_exp * if (uaname) GDKfree(uaname); return e; + } else if (is_sql_update_where(f)) { /* the is_sql_update_where test must come before is_sql_where, because is_sql_update_where are handled with sql_where */ + char *uaname = GDKmalloc(strlen(aname) + 1); + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clauses inside UPDATE statements (use subquery)", + uaname ? toUpperCopy(uaname, aname) : aname); + if (uaname) + GDKfree(uaname); + return e; } else if (is_sql_join(f)) { /* the is_sql_join test must come before is_sql_where, because the join conditions are handled with sql_where */ char *uaname = GDKmalloc(strlen(aname) + 1); sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in JOIN conditions", @@ -3260,6 +3267,13 @@ static sql_exp * if (uaname) GDKfree(uaname); return e; + } else if (is_sql_update_set(f)) { + char *uaname = GDKmalloc(strlen(aname) + 1); + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in UPDATE SET clause (use subquery)", + uaname ? toUpperCopy(uaname, aname) : aname); + if (uaname) + GDKfree(uaname); + return e; } else if (is_sql_aggr(f)) { char *uaname = GDKmalloc(strlen(aname) + 1); sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", @@ -3301,21 +3315,36 @@ static sql_exp * all_freevar &= (is_freevar(e)>0); list_append(exps, e); } - if (all_aggr && !all_freevar) { - char *uaname = GDKmalloc(strlen(aname) + 1); - sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", - uaname ? toUpperCopy(uaname, aname) : aname); - if (uaname) - GDKfree(uaname); - return e; - } - if (is_sql_groupby(f) && !all_freevar) { - char *uaname = GDKmalloc(strlen(aname) + 1); - sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate function '%s' not allowed in GROUP BY clause", - uaname ? toUpperCopy(uaname, aname) : aname, aname); - if (uaname) - GDKfree(uaname); - return e; + if (!all_freevar) { + if (all_aggr) { + char *uaname = GDKmalloc(strlen(aname) + 1); + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions cannot be nested", + uaname ? toUpperCopy(uaname, aname) : aname); + if (uaname) + GDKfree(uaname); + return e; + } else if (is_sql_groupby(f)) { + char *uaname = GDKmalloc(strlen(aname) + 1); + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate function '%s' not allowed in GROUP BY clause", + uaname ? toUpperCopy(uaname, aname) : aname, aname); + if (uaname) + GDKfree(uaname); + return e; + } else if (is_sql_join(f)) { /* the is_sql_join test must come before is_sql_where, because the join conditions are handled with sql_where */ + char *uaname = GDKmalloc(strlen(aname) + 1); + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in JOIN conditions", + uaname ? toUpperCopy(uaname, aname) : aname); + if (uaname) + GDKfree(uaname); + return e; + } else if (is_sql_where(f)) { + char *uaname = GDKmalloc(strlen(aname) + 1); + sql_exp *e = sql_error(sql, 02, SQLSTATE(42000) "%s: aggregate functions not allowed in WHERE clause", + uaname ? toUpperCopy(uaname, aname) : aname); + if (uaname) + GDKfree(uaname); + return e; + } } } @@ -3331,13 +3360,19 @@ static sql_exp * } int sql_state = query_fetch_outer_state(query,all_freevar-1); res = groupby = query_fetch_outer(query, all_freevar-1); - if (exp && is_sql_aggr(sql_state) && !is_groupby_col(res, exp)) { - char *uaname = GDKmalloc(strlen(aname) + 1); - sql_exp *e = sql_error(sql, 05, SQLSTATE(42000) "%s: aggregate function calls cannot be nested", - uaname ? toUpperCopy(uaname, aname) : aname); - if (uaname) - GDKfree(uaname); - return e; + if (exp && !is_groupby_col(res, exp)) { + if (is_sql_groupby(sql_state)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate function '%s' not allowed in GROUP BY clause", aname); + if (is_sql_aggr(sql_state)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate function calls cannot be nested"); + if (is_sql_update_where(sql_state)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clauses inside UPDATE statements"); + if (is_sql_update_set(sql_state)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in UPDATE SET clause"); + if (is_sql_join(sql_state)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in JOIN conditions"); + if (is_sql_where(sql_state)) + return sql_error(sql, 05, SQLSTATE(42000) "SELECT: aggregate functions not allowed in WHERE clause"); } } @@ -4570,9 +4605,10 @@ rel_rankop(sql_query *query, sql_rel **r is_nth_value = !strcmp(aname, "nth_value"); supports_frames = window_function->token != SQL_RANK || is_nth_value || !strcmp(aname, "first_value") || !strcmp(aname, "last_value"); - if (is_sql_join(f) || is_sql_where(f) || is_sql_groupby(f) || is_sql_having(f)) { + if (is_sql_update_set(f) || is_sql_update_where(f) || is_sql_join(f) || is_sql_where(f) || is_sql_groupby(f) || is_sql_having(f)) { char *uaname = GDKmalloc(strlen(aname) + 1); - const char *clause = is_sql_join(f)?"JOIN conditions":is_sql_where(f)?"WHERE clause":is_sql_groupby(f)?"GROUP BY clause":"HAVING clause"; + const char *clause = is_sql_update_set(f)?"UPDATE SET clause (use subquery)":is_sql_update_where(f)?"WHERE clause inside updates (use subquery)": + is_sql_join(f)?"JOIN conditions":is_sql_where(f)?"WHERE clause":is_sql_groupby(f)?"GROUP BY clause":"HAVING clause"; (void) sql_error(sql, 02, SQLSTATE(42000) "%s: window function '%s' not allowed in %s", uaname ? toUpperCopy(uaname, aname) : aname, aname, clause); if (uaname) diff --git a/sql/server/rel_updates.c b/sql/server/rel_updates.c --- a/sql/server/rel_updates.c +++ b/sql/server/rel_updates.c @@ -964,12 +964,12 @@ update_generate_assignments(sql_query *q int status = sql->session->status; exp_kind ek = {type_value, (single)?card_column:card_relation, FALSE}; - if(single && a->token == SQL_DEFAULT) { + if (single && a->token == SQL_DEFAULT) { char *colname = assignment->h->next->data.sval; sql_column *col = mvc_bind_column(sql, t, colname); if (col->def) { char *typestr = subtype2string2(&col->type); - if(!typestr) + if (!typestr) return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); v = rel_parse_val(sql, sa_message(sql->sa, "select cast(%s as %s);", col->def, typestr), sql->emode, NULL); _DELETE(typestr); @@ -977,7 +977,7 @@ update_generate_assignments(sql_query *q return sql_error(sql, 02, SQLSTATE(42000) "%s: column '%s' has no valid default value", action, col->base.name); } } else if (single) { - v = rel_value_exp(query, &rel_val, a, sql_sel, ek); + v = rel_value_exp(query, &rel_val, a, sql_sel | sql_update_set, ek); outer = 1; } else { rel_val = rel_subquery(query, NULL, a, ek); @@ -988,9 +988,9 @@ update_generate_assignments(sql_query *q assert(!rel_val); outer = 1; if (single) { - v = rel_value_exp(query, &r, a, sql_sel, ek); + v = rel_value_exp(query, &r, a, sql_sel | sql_update_set, ek); } else if (!rel_val && r) { - query_push_outer(query, r, sql_sel); + query_push_outer(query, r, sql_sel | sql_update_set); rel_val = rel_subquery(query, NULL, a, ek); r = query_pop_outer(query); if (/* DISABLES CODE */ (0) && r) { @@ -1157,11 +1157,11 @@ update_table(sql_query *query, dlist *qn if (!table_privs(sql, t, PRIV_SELECT)) return sql_error(sql, 02, SQLSTATE(42000) "UPDATE: insufficient privileges for user '%s' to update table '%s'", stack_get_string(sql, "current_user"), tname); - r = rel_logical_exp(query, NULL, opt_where, sql_where); + r = rel_logical_exp(query, NULL, opt_where, sql_where | sql_update_where); if (!r) { sql->errstr[0] = 0; sql->session->status = status; - r = rel_logical_exp(query, res, opt_where, sql_where); + r = rel_logical_exp(query, res, opt_where, sql_where | sql_update_where); if (!r) return NULL; /* handle join */ @@ -1240,7 +1240,7 @@ delete_table(sql_query *query, dlist *qn if (!table_privs(sql, t, PRIV_SELECT)) return sql_error(sql, 02, SQLSTATE(42000) "DELETE FROM: insufficient privileges for user '%s' to delete from table '%s'", stack_get_string(sql, "current_user"), tname); - r = rel_logical_exp(query, NULL, opt_where, sql_where); + r = rel_logical_exp(query, NULL, opt_where, sql_where | sql_update_where); if (r) { /* simple predicate which is not using the to be updated table. We add a select all */ sql_rel *l = rel_basetable(sql, t, t->base.name ); @@ -1253,7 +1253,7 @@ delete_table(sql_query *query, dlist *qn for (node *nn = r->exps->h ; nn ; nn = nn->next) exp_setname(sql->sa, (sql_exp*) nn->data, alias, NULL); //the last parameter is optional, hence NULL } - r = rel_logical_exp(query, r, opt_where, sql_where); + r = rel_logical_exp(query, r, opt_where, sql_where | sql_update_where); } if (!r) return NULL; @@ -1412,7 +1412,7 @@ merge_into_table(sql_query *query, dlist _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list