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

Reply via email to