Changeset: 2e8cc2bb05b1 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2e8cc2bb05b1
Modified Files:
sql/backends/monet5/rel_bin.c
sql/server/rel_updates.c
Branch: join-idx-improvements
Log Message:
Fixes wrong-key-error.Bug-6982 by improving join index insertion validation
diffs (82 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
@@ -4095,20 +4095,37 @@ insert_check_fkey(backend *be, list *ins
sql_subtype *bt = sql_bind_localtype("bit");
sql_subfunc *ne = sql_bind_func_result(sql, "sys", "<>", F_FUNC, true,
bt, 2, lng, lng);
+ stmt *nonil_rows = NULL;
for (node *m = k->columns->h; m; m = m->next) {
sql_kc *c = m->data;
/* foreach column add predicate */
stmt_add_column_predicate(be, c->c);
- }
-
- if (pin && list_length(pin->op4.lval))
+
+ // foreach column aggregate the nonil (literally 'null') values.
+ // mind that null values are valid fkeys with undefined value so
+ // we won't have an entry for them in the idx_inserts col
+ s = list_fetch(inserts, c->c->colnr);
+ nonil_rows = stmt_selectnonil(be, s, nonil_rows);
+ }
+
+ if (!s && pin && list_length(pin->op4.lval))
s = pin->op4.lval->h->data;
+
+ // we want to make sure that the data column(s) has the same number
+ // of (nonil) rows as the index column. if that is **not** the case
+ // then we are obviously dealing with an invalid foreign key
if (s->key && s->nrcols == 0) {
- s = stmt_binop(be, stmt_aggr(be, idx_inserts, NULL, NULL, cnt,
1, 0, 1), stmt_atom_lng(be, 1), NULL, ne);
+ s = stmt_binop(be,
+ stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
+ stmt_aggr(be, const_column(be, nonil_rows), NULL, NULL,
cnt, 1, 1, 1),
+ NULL, ne);
} else {
- /* releqjoin.count <> inserts[col1].count */
- s = stmt_binop(be, stmt_aggr(be, idx_inserts, NULL, NULL, cnt,
1, 0, 1), stmt_aggr(be, column(be, s), NULL, NULL, cnt, 1, 0, 1), NULL, ne);
+ /* relThetaJoin.notNull.count <> inserts[notNull(col1) && ...
&& notNull(colN)].count */
+ s = stmt_binop(be,
+ stmt_aggr(be, idx_inserts, NULL, NULL, cnt, 1, 1, 1),
+ stmt_aggr(be, column(be, nonil_rows), NULL, NULL, cnt,
1, 1, 1),
+ NULL, ne);
}
/* s should be empty */
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
@@ -142,11 +142,13 @@ static sql_rel *
rel_insert_join_idx(mvc *sql, const char* alias, sql_idx *i, sql_rel *inserts)
{
char *iname = sa_strconcat( sql->sa, "%", i->base.name);
- int need_nulls = 0;
node *m, *o;
sql_trans *tr = sql->session->tr;
sql_key *rk = (sql_key*)os_find_id(tr->cat->objects, tr,
((sql_fkey*)i->key)->rkey);
sql_rel *rt = rel_basetable(sql, rk->t, rk->t->base.name);
+ int need_nulls = 0, selfref = (rk->t == i->t);
+ if (selfref)
+ printf("#selfref\n");
sql_subtype *bt = sql_bind_localtype("bit");
sql_subfunc *or = sql_bind_func_result(sql, "sys", "or", F_FUNC, true,
bt, 2, bt, bt);
@@ -162,6 +164,7 @@ rel_insert_join_idx(mvc *sql, const char
if (c->c->null)
need_nulls = 1;
}
+ need_nulls = 0;
/* NULL and NOT NULL, for 'SIMPLE MATCH' semantics */
/* AND joins expressions */
for (m = i->columns->h, o = rk->columns->h; m && o; m = m->next, o =
o->next) {
@@ -213,7 +216,7 @@ rel_insert_join_idx(mvc *sql, const char
}
pexps = rel_projections(sql, nnlls, NULL, 1, 1);
- nnlls = rel_crossproduct(sql->sa, nnlls, rt, op_join);
+ nnlls = rel_crossproduct(sql->sa, nnlls, rt, op_left/*op_join*/);
nnlls->exps = join_exps;
nnlls = rel_project(sql->sa, nnlls, pexps);
/* add row numbers */
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]