Changeset: 5c85f16abd60 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=5c85f16abd60 Modified Files: monetdb5/modules/atoms/uuid.c sql/server/rel_exp.c sql/server/rel_psm.c sql/server/rel_select.c sql/test/miscellaneous/Tests/simple_selects.sql sql/test/miscellaneous/Tests/simple_selects.stable.out Branch: default Log Message:
Merge with Oct2020 branch. diffs (truncated from 319 to 300 lines): diff --git a/monetdb5/modules/atoms/uuid.c b/monetdb5/modules/atoms/uuid.c --- a/monetdb5/modules/atoms/uuid.c +++ b/monetdb5/modules/atoms/uuid.c @@ -284,8 +284,9 @@ UUIDgenerateUuidInt_bulk(bat *ret, const bn->tnonil = true; bn->tnil = false; BATsetcount(bn, n); - bn->tsorted = n < 2; - bn->tkey = n < 2; + bn->tsorted = n <= 1; + bn->trevsorted = n <= 1; + bn->tkey = n <= 1; bailout: if (msg && bn) diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c --- a/sql/server/rel_exp.c +++ b/sql/server/rel_exp.c @@ -228,6 +228,26 @@ exp_or(sql_allocator *sa, list *l, list return e; } +static int /* if the quantifier has to be upcasted, ignore the upper conversion for the cardinalilty */ +quantifier_has_rel(sql_exp *e) +{ + if (!e) + return 0; + switch(e->type){ + case e_convert: + return quantifier_has_rel(e->l); + case e_psm: + return exp_is_rel(e); + case e_atom: + case e_column: + case e_func: + case e_aggr: + case e_cmp: + return 0; + } + return 0; +} + sql_exp * exp_in(sql_allocator *sa, sql_exp *l, list *r, int cmptype) { @@ -241,7 +261,7 @@ exp_in(sql_allocator *sa, sql_exp *l, li for (node *n = r->h; n ; n = n->next) { sql_exp *next = n->data; - if (!exp_is_rel(next) && exps_card < next->card) + if (!quantifier_has_rel(next) && exps_card < next->card) exps_card = next->card; } e->card = MAX(l->card, exps_card); @@ -276,10 +296,10 @@ exp_in_func(mvc *sql, sql_exp *le, sql_e for (node *n = ((list*)vals->f)->h ; n ; n = n->next) { sql_exp *next = n->data; - if (!exp_is_rel(next) && exps_card < next->card) + if (!quantifier_has_rel(next) && exps_card < next->card) exps_card = next->card; } - } else if (!exp_is_rel(vals)) + } else if (!quantifier_has_rel(vals)) exps_card = vals->card; e->card = MAX(le->card, exps_card); @@ -300,7 +320,7 @@ exp_compare_func(mvc *sql, sql_exp *le, if (e) { e->flag = quantifier; /* At ANY and ALL operators, the cardinality on the right side is ignored if it is a sub-relation */ - e->card = quantifier && exp_is_rel(re) ? le->card : MAX(le->card, re->card); + e->card = quantifier && quantifier_has_rel(re) ? le->card : MAX(le->card, re->card); if (!has_nil(le) && !has_nil(re)) set_has_no_nil(e); } diff --git a/sql/server/rel_psm.c b/sql/server/rel_psm.c --- a/sql/server/rel_psm.c +++ b/sql/server/rel_psm.c @@ -622,6 +622,29 @@ rel_select_with_into(sql_query *query, s return rel_psm_block(query->sql->sa, reslist); } +static int while_exps_find_one_return(list *l); + +static int +while_exp_find_one_return(sql_exp *e) +{ + if (e->flag & PSM_RETURN) + return 1; + if (e->flag & PSM_WHILE) + return while_exps_find_one_return(e->r); + if (e->flag & PSM_IF) + return while_exps_find_one_return(e->r) || (e->f && while_exps_find_one_return(e->f)); + return 0; +} + +static int +while_exps_find_one_return(list *l) +{ + int res = 0; + for (node *n = l->h ; n && !res; n = n->next) + res |= while_exp_find_one_return(n->data); + return res; +} + static int has_return( list *l ); static int @@ -630,8 +653,10 @@ exp_has_return(sql_exp *e) if (e->type == e_psm) { if (e->flag & PSM_RETURN) return 1; - if (e->flag & PSM_IF) - return has_return(e->r) && (!e->f || has_return(e->f)); + if (e->flag & PSM_IF) /* for if, both sides must exist and both must have a return */ + return has_return(e->r) && e->f && has_return(e->f); + if (e->flag & PSM_WHILE) /* for while, at least one of the statements must have a return */ + return while_exps_find_one_return(e->r); } return 0; } @@ -640,10 +665,9 @@ static int has_return( list *l ) { node *n = l->t; - sql_exp *e = n->data; /* last statment of sequential block */ - if (exp_has_return(e)) + if (n && exp_has_return(n->data)) return 1; return 0; } 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 @@ -1550,7 +1550,7 @@ static sql_rel * rel_compare_exp_(sql_query *query, sql_rel *rel, sql_exp *ls, sql_exp *rs, sql_exp *rs2, int type, int anti, int quantifier, int f) { mvc *sql = query->sql; - sql_exp *L = ls, *R = rs, *e = NULL; + sql_exp *e = NULL; if (quantifier || exp_is_rel(ls) || exp_is_rel(rs)) { if (rs2) { @@ -1558,7 +1558,7 @@ rel_compare_exp_(sql_query *query, sql_r if (anti) set_anti(e); } else { - if (rel_binop_check_types(sql, rel, ls, rs, 0) < 0) + if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; e = exp_compare_func(sql, ls, rs, compare_func((comp_type)type, quantifier?0:anti), quantifier); if (anti && quantifier) @@ -1569,22 +1569,18 @@ rel_compare_exp_(sql_query *query, sql_r } else if (!rs2) { if (ls->card < rs->card) { sql_exp *swap = ls; - ls = rs; rs = swap; - - swap = L; - L = R; - R = swap; - type = (int)swap_compare((comp_type)type); } if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; e = exp_compare(sql->sa, ls, rs, type); } else { - if ((rs = exp_check_type(sql, exp_subtype(ls), rel, rs, type_equal)) == NULL || - (rs2 && (rs2 = exp_check_type(sql, exp_subtype(ls), rel, rs2, type_equal)) == NULL)) + assert(rs2); + if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) + return NULL; + if (!(rs2 = exp_check_type(sql, exp_subtype(ls), rel, rs2, type_equal))) return NULL; e = exp_compare2(sql->sa, ls, rs, rs2, type); } @@ -1607,7 +1603,7 @@ rel_compare_exp_(sql_query *query, sql_r else return sql_error(sql, ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results without an aggregate function"); } - return rel_select_push_exp_down(sql, rel, e, ls, L, rs, R, rs2, f); + return rel_select_push_exp_down(sql, rel, e, ls, ls, rs, rs, rs2, f); } static sql_rel * @@ -1624,7 +1620,7 @@ rel_compare_exp(sql_query *query, sql_re /* TODO to handle filters here */ sql_exp *e; - if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal) < 0) + if (rel_convert_types(sql, rel, rel, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; e = rel_binop_(sql, rel, ls, rs, NULL, compare_op, card_value); @@ -2219,7 +2215,7 @@ rel_logical_value_exp(sql_query *query, cmp_type = swap_compare(cmp_type); } - if (rel_binop_check_types(sql, rel ? *rel : NULL, ls, rs, 0) < 0) + if (rel_convert_types(sql, rel ? *rel : NULL, rel ? *rel : NULL, &ls, &rs, 1, type_equal_no_any) < 0) return NULL; if (exp_is_null(ls) && exp_is_null(rs)) return exp_atom(sql->sa, atom_general(sql->sa, sql_bind_localtype("bit"), NULL)); @@ -5070,6 +5066,12 @@ exp_has_rank(sql_exp *e) /* fall through */ case e_aggr: return exps_has_rank(e->l); + case e_cmp: + if (e->flag == cmp_or || e->flag == cmp_filter) + return exps_has_rank(e->l) || exps_has_rank(e->r); + if (e->flag == cmp_in || e->flag == cmp_notin) + return exp_has_rank(e->l) || exps_has_rank(e->r); + return exp_has_rank(e->l) || exp_has_rank(e->r) || (e->f && exp_has_rank(e->f)); default: return 0; } diff --git a/sql/test/Dependencies/dependency_functions.sql b/sql/test/Dependencies/dependency_functions.sql --- a/sql/test/Dependencies/dependency_functions.sql +++ b/sql/test/Dependencies/dependency_functions.sql @@ -22,6 +22,8 @@ BEGIN IF f1() < 0 THEN RETURN 2; + ELSE + RETURN 3; END IF; END; @@ -31,6 +33,8 @@ RETURNS int BEGIN IF f1() < 0 THEN RETURN 1; + ELSE + RETURN 2; END IF; END; diff --git a/sql/test/miscellaneous/Tests/simple_selects.sql b/sql/test/miscellaneous/Tests/simple_selects.sql --- a/sql/test/miscellaneous/Tests/simple_selects.sql +++ b/sql/test/miscellaneous/Tests/simple_selects.sql @@ -231,6 +231,21 @@ select 1, null intersect select 1, null; -- 1 NULL start transaction; +create or replace function ups() returns int begin if null > 1 then return 1; else return 2; end if; end; +select ups(); + -- 2 +create or replace function ups() returns int begin while 1 = 1 do if null is null then return 1; else return 2; end if; end while; end; +select ups(); + -- 1 +create or replace function ups() returns int begin declare a int; set a = 2; while a < 2 do if null is null then return 3; else set a = 2; end if; end while; end; +select ups(); + -- 3 +create or replace function ups() returns int begin if 1 > 1 then return 1; end if; end; --error, return missing +rollback; + +create or replace function ups() returns int begin declare a int; while 1 = 1 do set a = 2; end while; end; --error, return missing + +start transaction; create function "😀"() returns int return 1; select "😀"(); -- 1 diff --git a/sql/test/miscellaneous/Tests/simple_selects.stable.err b/sql/test/miscellaneous/Tests/simple_selects.stable.err --- a/sql/test/miscellaneous/Tests/simple_selects.stable.err +++ b/sql/test/miscellaneous/Tests/simple_selects.stable.err @@ -274,6 +274,14 @@ MAPI = (monetdb) /var/tmp/mtest-921778/ QUERY = select x as z, y as z from (select 1, 2) as x(x,y) order by z; ERROR = !SELECT: identifier 'z' ambiguous CODE = 42000 +MAPI = (monetdb) /var/tmp/mtest-331513/.s.monetdb.32675 +QUERY = create or replace function ups() returns int begin if 1 > 1 then return 1; end if; end; --error, return missing +ERROR = !CREATE FUNCTION: missing return statement +CODE = 42000 +MAPI = (monetdb) /var/tmp/mtest-408341/.s.monetdb.34589 +QUERY = create or replace function ups() returns int begin declare a int; while 1 = 1 do set a = 2; end while; end; --error, return missing +ERROR = !CREATE FUNCTION: missing return statement +CODE = 42000 # 17:31:38 > # 17:31:38 > "Done." diff --git a/sql/test/miscellaneous/Tests/simple_selects.stable.out b/sql/test/miscellaneous/Tests/simple_selects.stable.out --- a/sql/test/miscellaneous/Tests/simple_selects.stable.out +++ b/sql/test/miscellaneous/Tests/simple_selects.stable.out @@ -442,6 +442,29 @@ project ( % 1, 0 # length [ 1, NULL ] #start transaction; +#create or replace function ups() returns int begin if null > 1 then return 1; else return 2; end if; end; +#select ups(); +% .%2 # table_name +% %2 # name +% int # type +% 1 # length +[ 2 ] _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list