static str AGGRgrouped2(bat *retval, bat *bid, bat *eid, int tp, BAT *(*grpfunc)(BAT *, BAT *, BAT *, BAT *, int, int, int), int skip_nils, const char *malfunc) { BAT *b, *g, *e; b = BATdescriptor(*bid); /* [gid,value] */ if (b == NULL) throw(MAL, "aggr.sum", RUNTIME_OBJECT_MISSING); g = BATmirror(BATmark(b, 0)); /* [dense,gid] */ e = BATmirror(BATmark(BATmirror(b), 0)); /* [dense,value] */ BBPreleaseref(b->batCacheid); b = e; e = BATdescriptor(*eid); /* [gid,any] */ return AGGRgrouped(retval, b, g, e, tp, grpfunc, skip_nils, malfunc); }
static str AGGRsubgroupedExt(bat *retval1, bat *retval2, bat *bid, bat *gid, bat *eid, bat *sid, int skip_nils, int abort_on_error, int tp, BAT *(*grpfunc1)(BAT *, BAT *, BAT *, BAT *, int, int, int), gdk_return (*grpfunc2)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *, int, int, int), BAT *(*quantilefunc)(BAT *, BAT *, BAT *, BAT *, int, double, int, int), bat *quantile, const char *malfunc) { BAT *b, *g, *e, *s, *bn = NULL, *cnts, *q = NULL; double qvalue; /* one of grpfunc1, grpfunc2 and quantilefunc is non-NULL and the others are */ assert((grpfunc1 && grpfunc2 == NULL && quantilefunc == NULL) || (grpfunc1 == NULL && grpfunc2 && quantilefunc == NULL) || (grpfunc1 == NULL && grpfunc2 == NULL && quantilefunc) ); /* if retval2 is non-NULL, we must have grpfunc2 */ assert(retval2 == NULL || grpfunc2 != NULL); b = BATdescriptor(*bid); g = gid ? BATdescriptor(*gid) : NULL; e = eid ? BATdescriptor(*eid) : NULL; q = quantile ? BATdescriptor(*quantile) : NULL; if (b == NULL || (gid != NULL && g == NULL) || (eid != NULL && e == NULL)) { if (b) BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } if (tp == TYPE_any && (grpfunc1 == BATgroupmedian || quantilefunc == BATgroupquantile)) tp = b->ttype; if (sid) { s = BATdescriptor(*sid); if (s == NULL) { BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } } else { if (!BAThdense(b)) { /* XXX backward compatibility code: ignore non-dense head, but * only if no candidate list */ s = BATmirror(BATmark(BATmirror(b), 0)); BBPreleaseref(b->batCacheid); b = s; } s = NULL; } if (grpfunc1) bn = (*grpfunc1)(b, g, e, s, tp, skip_nils, abort_on_error); if (quantilefunc) { assert(BATcount(q)>0); assert(q->ttype == TYPE_dbl); qvalue = ((const double *)Tloc(q, BUNfirst(q)))[0]; if (qvalue < 0|| qvalue > 1) { char *s; s = createException(MAL, malfunc, "quantile value of %f is not in range [0,1]", qvalue); return s; } bn = (*quantilefunc)(b, g, e, s, tp, qvalue, skip_nils, abort_on_error); } if (grpfunc2 && (*grpfunc2)(&bn, retval2 ? &cnts : NULL, b, g, e, s, tp, skip_nils, abort_on_error) == GDK_FAIL) bn = NULL; BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); if (s) BBPreleaseref(s->batCacheid); if (bn == NULL) { char *errbuf = GDKerrbuf; char *s; if (errbuf && *errbuf) { if (strncmp(errbuf, "!ERROR: ", 8) == 0) errbuf += 8; if (strchr(errbuf, '!') == errbuf + 5) { s = createException(MAL, malfunc, "%s", errbuf); } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') { s = createException(MAL, malfunc, "%s", s + 2); } else { s = createException(MAL, malfunc, "%s", errbuf); } *GDKerrbuf = 0; return s; } throw(MAL, malfunc, OPERATION_FAILED); } *retval1 = bn->batCacheid; BBPkeepref(bn->batCacheid); if (retval2) { *retval2 = cnts->batCacheid; BBPkeepref(cnts->batCacheid); } return MAL_SUCCEED; }
/* * grouped aggregates */ static str AGGRgrouped(bat *retval1, bat *retval2, BAT *b, BAT *g, BAT *e, int tp, BAT *(*grpfunc1)(BAT *, BAT *, BAT *, BAT *, int, int, int), gdk_return (*grpfunc2)(BAT **, BAT **, BAT *, BAT *, BAT *, BAT *, int, int, int), BAT *(*quantilefunc)(BAT *, BAT *, BAT *, BAT *, int, double, int, int), BAT *quantile, int skip_nils, const char *malfunc) { BAT *bn, *cnts = NULL, *t, *map; double qvalue; /* one of grpfunc1, grpfunc2 and quantilefunc is non-NULL and the others are */ assert((grpfunc1 != NULL && grpfunc2 == NULL && quantilefunc == NULL) || (grpfunc1 == NULL && grpfunc2 != NULL && quantilefunc == NULL) || (grpfunc1 == NULL && grpfunc2 == NULL && quantilefunc != NULL) ); /* if retval2 is non-NULL, we must have grpfunc2 */ assert(retval2 == NULL || grpfunc2 != NULL); assert(quantile == NULL || quantilefunc != NULL); if (b == NULL || g == NULL || e == NULL) { if (b) BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } if (tp == TYPE_any && (grpfunc1 == BATgroupmedian || quantilefunc == BATgroupquantile)) tp = b->ttype; if (!BAThdense(b) || !BAThdense(g)) { /* if b or g don't have a dense head, replace the head with a * dense sequence */ t = BATjoin(BATmirror(b), g, MIN(BATcount(b), BATcount(g))); BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); b = BATmirror(BATmark(t, 0)); g = BATmirror(BATmark(BATmirror(t), 0)); BBPreleaseref(t->batCacheid); } if (b->hseqbase != g->hseqbase || BATcount(b) != BATcount(g)) { /* b and g are not aligned: align them by creating a view on * one or the other */ oid min; /* lowest common oid */ oid max; /* highest common oid */ min = b->hseqbase; if (min < g->hseqbase) min = g->hseqbase; max = b->hseqbase + BATcount(b); if (g->hseqbase + BATcount(g) < max) max = g->hseqbase + BATcount(g); if (b->hseqbase != min || b->hseqbase + BATcount(b) != max) { if (min >= max) min = max = b->hseqbase; t = BATslice(b, BUNfirst(b) + (BUN) (min - b->hseqbase), BUNfirst(b) + (BUN) (max - b->hseqbase)); BBPreleaseref(b->batCacheid); b = t; } if (g->hseqbase != min || g->hseqbase + BATcount(g) != max) { if (min >= max) min = max = g->hseqbase; t = BATslice(g, BUNfirst(g) + (BUN) (min - g->hseqbase), BUNfirst(g) + (BUN) (max - g->hseqbase)); BBPreleaseref(g->batCacheid); g = t; } } if (!BAThdense(e)) { /* if e doesn't have a dense head, renumber the group ids with * a dense sequence at the cost of some left joins */ map = BATmark(e, 0); /* [gid,newgid(dense)] */ BBPreleaseref(e->batCacheid); e = BATmirror(map); /* [newgid(dense),gid] */ t = BATleftjoin(g, map, BATcount(g)); /* [oid,newgid] */ BBPreleaseref(g->batCacheid); g = t; } else { map = NULL; } if (grpfunc1) bn = (*grpfunc1)(b, g, e, NULL, tp, skip_nils, 1); if (quantilefunc) { assert(BATcount(quantile)>0); assert(quantile->ttype == TYPE_dbl); qvalue = ((const double *)Tloc(quantile, BUNfirst(quantile)))[0]; if (qvalue < 0|| qvalue > 1) { char *s; s = createException(MAL, malfunc, "quantile value of %f is not in range [0,1]", qvalue); return s; } bn = (*quantilefunc)(b, g, e, NULL, tp, qvalue, skip_nils, 1); } if (grpfunc2 && (*grpfunc2)(&bn, retval2 ? &cnts : NULL, b, g, e, NULL, tp, skip_nils, 1) == GDK_FAIL) bn = NULL; if (bn != NULL && (grpfunc1 == BATgroupmin || grpfunc1 == BATgroupmax)) { t = BATproject(bn, b); BBPreleaseref(bn->batCacheid); bn = t; } BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); if (map == NULL) /* if map!=NULL, e is mirror of map */ BBPreleaseref(e->batCacheid); if (bn == NULL) { char *errbuf = GDKerrbuf; char *s; if (map) BBPreleaseref(map->batCacheid); if (errbuf && *errbuf) { if (strncmp(errbuf, "!ERROR: ", 8) == 0) errbuf += 8; if (strchr(errbuf, '!') == errbuf + 5) { s = createException(MAL, malfunc, "%s", errbuf); } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') { s = createException(MAL, malfunc, "%s", s + 2); } else { s = createException(MAL, malfunc, "%s", errbuf); } *GDKerrbuf = 0; return s; } throw(MAL, malfunc, OPERATION_FAILED); } if (map) { t = BATleftjoin(map, bn, BATcount(bn)); BBPreleaseref(bn->batCacheid); bn = t; if (cnts) { t = BATleftjoin(map, cnts, BATcount(cnts)); BBPreleaseref(cnts->batCacheid); cnts = t; } BBPreleaseref(map->batCacheid); } *retval1 = bn->batCacheid; BBPkeepref(bn->batCacheid); if (retval2) { *retval2 = cnts->batCacheid; BBPkeepref(cnts->batCacheid); } return MAL_SUCCEED; }
static str AGGRsubgrouped(bat *retval, bat *bid, bat *gid, bat *eid, bat *sid, int skip_nils, int abort_on_error, int tp, BAT *(*grpfunc)(BAT *, BAT *, BAT *, BAT *, int, int, int), const char *malfunc) { BAT *b, *g, *e, *s, *bn; b = BATdescriptor(*bid); g = gid ? BATdescriptor(*gid) : NULL; e = eid ? BATdescriptor(*eid) : NULL; if (b == NULL || (gid != NULL && g == NULL) || (eid != NULL && e == NULL)) { if (b) BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } if (tp == TYPE_any && grpfunc == BATgroupmedian) tp = b->ttype; if (sid) { s = BATdescriptor(*sid); if (s == NULL) { BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } } else { if (!BAThdense(b)) { /* XXX backward compatibility code: ignore non-dense head, but * only if no candidate list */ s = BATmirror(BATmark(BATmirror(b), 0)); BBPreleaseref(b->batCacheid); b = s; } s = NULL; } bn = (*grpfunc)(b, g, e, s, tp, skip_nils, abort_on_error); BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); if (s) BBPreleaseref(s->batCacheid); if (bn == NULL) { char *errbuf = GDKerrbuf; char *s; if (errbuf && *errbuf) { if (strncmp(errbuf, "!ERROR: ", 8) == 0) errbuf += 8; if (strchr(errbuf, '!') == errbuf + 5) { s = createException(MAL, malfunc, "%s", errbuf); } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') { s = createException(MAL, malfunc, "%s", s + 2); } else { s = createException(MAL, malfunc, "%s", errbuf); } *GDKerrbuf = 0; return s; } throw(MAL, malfunc, OPERATION_FAILED); } *retval = bn->batCacheid; BBPkeepref(bn->batCacheid); return MAL_SUCCEED; }
/* * grouped aggregates */ static str AGGRgrouped(bat *retval, BAT *b, BAT *g, BAT *e, int tp, BAT *(*grpfunc)(BAT *, BAT *, BAT *, BAT *, int, int, int), int skip_nils, const char *malfunc) { BAT *bn, *t, *map; if (b == NULL || g == NULL || e == NULL) { if (b) BBPreleaseref(b->batCacheid); if (g) BBPreleaseref(g->batCacheid); if (e) BBPreleaseref(e->batCacheid); throw(MAL, malfunc, RUNTIME_OBJECT_MISSING); } if (tp == TYPE_any && grpfunc == BATgroupmedian) tp = b->ttype; if (!BAThdense(b) || !BAThdense(g)) { /* if b or g don't have a dense head, replace the head with a * dense sequence */ t = BATjoin(BATmirror(b), g, MIN(BATcount(b), BATcount(g))); BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); b = BATmirror(BATmark(t, 0)); g = BATmirror(BATmark(BATmirror(t), 0)); BBPreleaseref(t->batCacheid); } if (b->hseqbase != g->hseqbase || BATcount(b) != BATcount(g)) { /* b and g are not aligned: align them by creating a view on * one or the other */ oid min; /* lowest common oid */ oid max; /* highest common oid */ min = b->hseqbase; if (min < g->hseqbase) min = g->hseqbase; max = b->hseqbase + BATcount(b); if (g->hseqbase + BATcount(g) < max) max = g->hseqbase + BATcount(g); if (b->hseqbase != min || b->hseqbase + BATcount(b) != max) { if (min >= max) min = max = b->hseqbase; t = BATslice(b, BUNfirst(b) + (BUN) (min - b->hseqbase), BUNfirst(b) + (BUN) (max - b->hseqbase)); BBPreleaseref(b->batCacheid); b = t; } if (g->hseqbase != min || g->hseqbase + BATcount(g) != max) { if (min >= max) min = max = g->hseqbase; t = BATslice(g, BUNfirst(g) + (BUN) (min - g->hseqbase), BUNfirst(g) + (BUN) (max - g->hseqbase)); BBPreleaseref(g->batCacheid); g = t; } } if (!BAThdense(e)) { /* if e doesn't have a dense head, renumber the group ids with * a dense sequence at the cost of some left joins */ map = BATmark(e, 0); /* [gid,newgid(dense)] */ BBPreleaseref(e->batCacheid); e = BATmirror(map); /* [newgid(dense),gid] */ t = BATleftjoin(g, map, BATcount(g)); /* [oid,newgid] */ BBPreleaseref(g->batCacheid); g = t; } else { map = NULL; } bn = (*grpfunc)(b, g, e, NULL, tp, skip_nils, 1); if (bn != NULL && (grpfunc == BATgroupmin || grpfunc == BATgroupmax)) { BAT *bnn = BATouterjoin(bn, b, BATcount(bn)); BBPreleaseref(bn->batCacheid); bn = bnn; } BBPreleaseref(b->batCacheid); BBPreleaseref(g->batCacheid); if (map == NULL) /* if map!=NULL, e is mirror of map */ BBPreleaseref(e->batCacheid); if (bn == NULL) { char *errbuf = GDKerrbuf; char *s; if (map) BBPreleaseref(map->batCacheid); if (errbuf && *errbuf) { if (strncmp(errbuf, "!ERROR: ", 8) == 0) errbuf += 8; if (strchr(errbuf, '!') == errbuf + 5) { s = createException(MAL, malfunc, "%s", errbuf); } else if ((s = strchr(errbuf, ':')) != NULL && s[1] == ' ') { s = createException(MAL, malfunc, "%s", s + 2); } else { s = createException(MAL, malfunc, "%s", errbuf); } *GDKerrbuf = 0; return s; } throw(MAL, malfunc, OPERATION_FAILED); } if (map) { t = BATleftjoin(map, bn, BATcount(bn)); BBPreleaseref(map->batCacheid); BBPreleaseref(bn->batCacheid); bn = t; } *retval = bn->batCacheid; BBPkeepref(bn->batCacheid); return MAL_SUCCEED; }