Changeset: 30a0486ffcdc for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=30a0486ffcdc Added Files: gdk/gdk_subquery.c gdk/gdk_subquery.h Modified Files: clients/Tests/exports.stable.out gdk/CMakeLists.txt sql/backends/monet5/sql_subquery.c Branch: default Log Message:
Cleanup, move subquery aggregation implementations to the GDK. Initializing group candidates is GDK specific, also it was not clean to throw a GDK error in the MAL layer. diffs (truncated from 2568 to 300 lines): diff --git a/clients/Tests/exports.stable.out b/clients/Tests/exports.stable.out --- a/clients/Tests/exports.stable.out +++ b/clients/Tests/exports.stable.out @@ -16,6 +16,11 @@ size_t ATOMlen(int id, const void *v); str ATOMname(int id); void *ATOMnil(int id) __attribute__((__malloc__)); int ATOMprint(int id, const void *val, stream *fd); +BAT *BATall_grp(BAT *l, BAT *g, BAT *e, BAT *s); +BAT *BATallnotequal_grp(BAT *l, BAT *r, BAT *g, BAT *e, BAT *s); +BAT *BATallnotequal_grp2(BAT *l, BAT *r, BAT *rid, BAT *g, BAT *e, BAT *s); +BAT *BATanyequal_grp(BAT *l, BAT *r, BAT *g, BAT *e, BAT *s); +BAT *BATanyequal_grp2(BAT *l, BAT *r, BAT *rid, BAT *g, BAT *e, BAT *s); gdk_return BATappend(BAT *b, BAT *n, BAT *s, bool force) __attribute__((__warn_unused_result__)); void BATassertProps(BAT *b); atomDesc BATatoms[]; @@ -162,6 +167,7 @@ void *BATmin_skipnil(BAT *b, void *aggr, gdk_return BATmode(BAT *b, bool transient); void BATmsync(BAT *b); gdk_return BATnegcands(BAT *cands, BAT *odels); +BAT *BATnil_grp(BAT *l, BAT *g, BAT *e, BAT *s); bool BATordered(BAT *b); bool BATordered_rev(BAT *b); gdk_return BATorderidx(BAT *b, bool stable); @@ -187,6 +193,8 @@ BAT *BATslice(BAT *b, BUN low, BUN high) gdk_return BATsort(BAT **sorted, BAT **order, BAT **groups, BAT *b, BAT *o, BAT *g, bool reverse, bool nilslast, bool stable) __attribute__((__warn_unused_result__)); gdk_return BATstr_group_concat(ValPtr res, BAT *b, BAT *s, BAT *sep, bool skip_nils, bool abort_on_error, bool nil_if_empty, const char *restrict separator); gdk_return BATsubcross(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, bool max_one) __attribute__((__warn_unused_result__)); +BAT *BATsubexist(BAT *l, BAT *g, BAT *e, BAT *s); +BAT *BATsubnot_exist(BAT *l, BAT *g, BAT *e, BAT *s); gdk_return BATsum(void *res, int tp, BAT *b, BAT *s, bool skip_nils, bool abort_on_error, bool nil_if_empty); gdk_return BATthetajoin(BAT **r1p, BAT **r2p, BAT *l, BAT *r, BAT *sl, BAT *sr, int op, bool nil_matches, BUN estimate) __attribute__((__warn_unused_result__)); BAT *BATthetaselect(BAT *b, BAT *s, const void *val, const char *op); diff --git a/gdk/CMakeLists.txt b/gdk/CMakeLists.txt --- a/gdk/CMakeLists.txt +++ b/gdk/CMakeLists.txt @@ -73,6 +73,7 @@ target_sources(gdk gdk_unique.c gdk_interprocess.c gdk_interprocess.h gdk_firstn.c + gdk_subquery.c gdk_subquery.h gdk_analytic_bounds.c gdk_analytic_func.c gdk_analytic.h diff --git a/gdk/gdk_subquery.c b/gdk/gdk_subquery.c new file mode 100644 --- /dev/null +++ b/gdk/gdk_subquery.c @@ -0,0 +1,990 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright 1997 - July 2008 CWI, August 2008 - 2020 MonetDB B.V. + */ + +#include "monetdb_config.h" +#include "gdk.h" +#include "gdk_subquery.h" +#include "gdk_private.h" +#include "gdk_calc_private.h" + +#define SQLall_grp_imp(TYPE) \ + do { \ + const TYPE *restrict vals = (const TYPE *) Tloc(l, 0); \ + TYPE *restrict rp = (TYPE *) Tloc(res, 0); \ + while (ncand > 0) { \ + ncand--; \ + i = canditer_next(&ci) - l->hseqbase; \ + if (gids == NULL || \ + (gids[i] >= min && gids[i] <= max)) { \ + if (gids) \ + gid = gids[i] - min; \ + else \ + gid = (oid) i; \ + if (oids[gid] != (BUN_NONE - 1)) { \ + if (oids[gid] == BUN_NONE) { \ + if (!is_##TYPE##_nil(vals[i])) \ + oids[gid] = i; \ + } else { \ + if (vals[oids[gid]] != vals[i] && !is_##TYPE##_nil(vals[i])) \ + oids[gid] = BUN_NONE - 1; \ + } \ + } \ + } \ + } \ + for (i = 0; i < ngrp; i++) { /* convert the found oids in values */ \ + BUN noid = oids[i]; \ + if (noid >= (BUN_NONE - 1)) { \ + rp[i] = TYPE##_nil; \ + hasnil = 1; \ + } else { \ + rp[i] = vals[noid]; \ + } \ + } \ + } while (0) + +BAT * +BATall_grp(BAT *l, BAT *g, BAT *e, BAT *s) +{ + BAT *res = NULL; + const oid *restrict gids; + oid gid, min, max, *restrict oids = NULL; /* The oids variable controls if we have found a nil in the group so far */ + BUN i, ngrp, ncand; + bit hasnil = 0; + struct canditer ci; + const char *err; + lng t0 = 0; + + TRC_DEBUG_IF(ALGO) t0 = GDKusec(); + + if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci, &ncand)) != NULL) { + GDKerror("%s\n", err); + return NULL; + } + if (g == NULL) { + GDKerror("l and g must be aligned\n"); + return NULL; + } + + if (BATcount(l) == 0 || ngrp == 0) { + const void *nilp = ATOMnilptr(l->ttype); + if ((res = BATconstant(ngrp == 0 ? 0 : min, l->ttype, nilp, ngrp, TRANSIENT)) == NULL) + goto alloc_fail; + } else { + if ((res = COLnew(min, l->ttype, ngrp, TRANSIENT)) == NULL) + goto alloc_fail; + if ((oids = GDKmalloc(ngrp * sizeof(oid))) == NULL) + goto alloc_fail; + + for (i = 0; i < ngrp; i++) + oids[i] = BUN_NONE; + + if (!g || BATtdense(g)) + gids = NULL; + else + gids = (const oid *) Tloc(g, 0); + + switch (l->ttype) { + case TYPE_bit: + SQLall_grp_imp(bit); + break; + case TYPE_bte: + SQLall_grp_imp(bte); + break; + case TYPE_sht: + SQLall_grp_imp(sht); + break; + case TYPE_int: + SQLall_grp_imp(int); + break; + case TYPE_lng: + SQLall_grp_imp(lng); + break; +#ifdef HAVE_HGE + case TYPE_hge: + SQLall_grp_imp(hge); + break; +#endif + case TYPE_flt: + SQLall_grp_imp(flt); + break; + case TYPE_dbl: + SQLall_grp_imp(dbl); + break; + default: { + int (*ocmp) (const void *, const void *) = ATOMcompare(l->ttype); + const void *restrict nilp = ATOMnilptr(l->ttype); + BATiter li = bat_iterator(l); + + while (ncand > 0) { + ncand--; + i = canditer_next(&ci) - l->hseqbase; + if (gids == NULL || + (gids[i] >= min && gids[i] <= max)) { + if (gids) + gid = gids[i] - min; + else + gid = (oid) i; + if (oids[gid] != (BUN_NONE - 1)) { + if (oids[gid] == BUN_NONE) { + if (ocmp(BUNtail(li, i), nilp) != 0) + oids[gid] = i; + } else { + const void *pi = BUNtail(li, oids[gid]); + const void *pp = BUNtail(li, i); + if (ocmp(pi, pp) != 0 && ocmp(pp, nilp) != 0) + oids[gid] = BUN_NONE - 1; + } + } + } + } + + for (i = 0; i < ngrp; i++) { /* convert the found oids in values */ + BUN noid = oids[i]; + void *next; + if (noid == BUN_NONE) { + next = (void*) nilp; + hasnil = 1; + } else { + next = BUNtail(li, noid); + } + if (BUNappend(res, next, false) != GDK_SUCCEED) + goto alloc_fail; + } + } + } + BATsetcount(res, ngrp); + res->tnil = hasnil != 0; + res->tnonil = hasnil == 0; + res->tkey = BATcount(res) <= 1; + res->tsorted = BATcount(res) <= 1; + res->trevsorted = BATcount(res) <= 1; + } + + GDKfree(oids); + + TRC_DEBUG(ALGO, "l=" ALGOBATFMT ",g=" ALGOBATFMT + ",e=" ALGOOPTBATFMT ",s=" ALGOOPTBATFMT + " -> " ALGOOPTBATFMT + " (%s -- " LLFMT " usec)\n", + ALGOBATPAR(l), ALGOBATPAR(g), + ALGOOPTBATPAR(e), ALGOOPTBATPAR(s), + ALGOOPTBATPAR(res), + __func__, GDKusec() - t0); + return res; +alloc_fail: + BBPreclaim(res); + GDKfree(oids); + return NULL; +} + +#define SQLnil_grp_imp(TYPE) \ + do { \ + const TYPE *restrict vals = (const TYPE *) Tloc(l, 0); \ + while (ncand > 0) { \ + ncand--; \ + i = canditer_next(&ci) - l->hseqbase; \ + if (gids == NULL || \ + (gids[i] >= min && gids[i] <= max)) { \ + if (gids) \ + gid = gids[i] - min; \ + else \ + gid = (oid) i; \ + if (ret[gid] != TRUE && is_##TYPE##_nil(vals[i])) \ + ret[gid] = TRUE; \ + } \ + } \ + } while (0) + +BAT * +BATnil_grp(BAT *l, BAT *g, BAT *e, BAT *s) +{ + BAT *res = NULL; + const oid *restrict gids; + oid gid, min, max; + BUN i, ngrp, ncand; + struct canditer ci; + const char *err; + lng t0 = 0; + + TRC_DEBUG_IF(ALGO) t0 = GDKusec(); + + if ((err = BATgroupaggrinit(l, g, e, s, &min, &max, &ngrp, &ci, &ncand)) != NULL) { + GDKerror("%s\n", err); + return NULL; + } + if (g == NULL) { + GDKerror("l and g must be aligned\n"); + return NULL; + } + + if (BATcount(l) == 0 || ngrp == 0) { + bit F = FALSE; + if ((res = BATconstant(ngrp == 0 ? 0 : min, TYPE_bit, &F, ngrp, TRANSIENT)) == NULL) + goto alloc_fail; + + } else { + bit *restrict ret; + + if ((res = COLnew(min, TYPE_bit, ngrp, TRANSIENT)) == NULL) + goto alloc_fail; + ret = (bit *) Tloc(res, 0); + memset(ret, FALSE, ngrp * sizeof(bit)); + + if (!g || BATtdense(g)) + gids = NULL; + else + gids = (const oid *) Tloc(g, 0); + + switch (l->ttype) { + case TYPE_bit: + SQLnil_grp_imp(bit); + break; + case TYPE_bte: + SQLnil_grp_imp(bte); + break; + case TYPE_sht: + SQLnil_grp_imp(sht); + break; _______________________________________________ checkin-list mailing list [email protected] https://www.monetdb.org/mailman/listinfo/checkin-list
