Changeset: db5af1da0713 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/db5af1da0713
Modified Files:
clients/Tests/exports.stable.out
gdk/gdk.h
gdk/gdk_batop.c
Branch: Jul2021
Log Message:
Implemented BAT{update,replace}pos to update/replace multiple values.
The locations are given by an array of positions, the new values by a BAT.
diffs (truncated from 317 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
@@ -181,6 +181,7 @@ BAT *BATproject2(BAT *restrict l, BAT *r
BAT *BATprojectchain(BAT **bats);
gdk_return BATrangejoin(BAT **r1p, BAT **r2p, BAT *l, BAT *rl, BAT *rh, BAT
*sl, BAT *sr, bool li, bool hi, bool anti, bool symmetric, BUN estimate)
__attribute__((__warn_unused_result__));
gdk_return BATreplace(BAT *b, BAT *p, BAT *n, bool force)
__attribute__((__warn_unused_result__));
+gdk_return BATreplacepos(BAT *b, const oid *positions, BAT *n, bool force)
__attribute__((__warn_unused_result__));
gdk_return BATroles(BAT *b, const char *tnme);
BAT *BATsample(BAT *b, BUN n);
BAT *BATsample_with_seed(BAT *b, BUN n, uint64_t seed);
@@ -204,6 +205,7 @@ void BATundo(BAT *b);
BAT *BATunique(BAT *b, BAT *s);
BAT *BATunmask(BAT *b);
gdk_return BATupdate(BAT *b, BAT *p, BAT *n, bool force)
__attribute__((__warn_unused_result__));
+gdk_return BATupdatepos(BAT *b, const oid *positions, BAT *n, bool force)
__attribute__((__warn_unused_result__));
BBPrec *BBP[N_BBPINIT];
gdk_return BBPaddfarm(const char *dirname, uint32_t rolemask, bool logerror);
void BBPclear(bat bid);
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -1091,6 +1091,10 @@ gdk_export gdk_return BATreplace(BAT *b,
__attribute__((__warn_unused_result__));
gdk_export gdk_return BATupdate(BAT *b, BAT *p, BAT *n, bool force)
__attribute__((__warn_unused_result__));
+gdk_export gdk_return BATreplacepos(BAT *b, const oid *positions, BAT *n, bool
force)
+ __attribute__((__warn_unused_result__));
+gdk_export gdk_return BATupdatepos(BAT *b, const oid *positions, BAT *n, bool
force)
+ __attribute__((__warn_unused_result__));
/* Functions to perform a binary search on a sorted BAT.
* See gdk_search.c for details. */
diff --git a/gdk/gdk_batop.c b/gdk/gdk_batop.c
--- a/gdk/gdk_batop.c
+++ b/gdk/gdk_batop.c
@@ -1143,24 +1143,48 @@ BATdel(BAT *b, BAT *d)
}
/*
- * The last in this series is a BATreplace, which replaces all the
- * buns mentioned.
+ * Replace all values in b with values from n whose location is given by
+ * the oid in either p or positions.
+ * If positions is used, autoincr specifies whether it is the first of a
+ * dense range of positions or whether it is a full-blown array of
+ * position.
+ * If mayappend is set, the position in p/positions may refer to
+ * locations beyond the end of b.
*/
static gdk_return
-BATappend_or_update(BAT *b, BAT *p, BAT *n, bool mayappend, bool force)
+BATappend_or_update(BAT *b, BAT *p, const oid *positions, BAT *n,
+ bool mayappend, bool autoincr, bool force)
{
lng t0 = GDKusec();
+ oid pos = oid_nil;
if (b == NULL || b->ttype == TYPE_void || p == NULL || n == NULL) {
return GDK_SUCCEED;
}
- if (BATcount(p) != BATcount(n)) {
- GDKerror("update BATs not the same size\n");
- return GDK_FAIL;
- }
- if (ATOMtype(p->ttype) != TYPE_oid) {
- GDKerror("positions BAT not type OID\n");
- return GDK_FAIL;
+ /* either p or positions */
+ assert((p == NULL) != (positions == NULL));
+ if (p != NULL) {
+ if (BATcount(p) != BATcount(n)) {
+ GDKerror("update BATs not the same size\n");
+ return GDK_FAIL;
+ }
+ if (ATOMtype(p->ttype) != TYPE_oid) {
+ GDKerror("positions BAT not type OID\n");
+ return GDK_FAIL;
+ }
+ if (BATtdense(p)) {
+ pos = p->tseqbase;
+ positions = &pos;
+ autoincr = true;
+ p = NULL;
+ } else if (p->ttype != TYPE_void) {
+ positions = (const oid *) Tloc(p, 0);
+ autoincr = false;
+ } else {
+ autoincr = false;
+ }
+ } else if (autoincr) {
+ pos = *positions;
}
if (BATcount(n) == 0) {
return GDK_SUCCEED;
@@ -1172,15 +1196,6 @@ BATappend_or_update(BAT *b, BAT *p, BAT
BATiter bi = bat_iterator_nolock(b);
BATiter ni = bat_iterator(n);
-#if 0 /* questionable: what if p point outside b, even if !mayappend? */
- if (BATcount(b) == 0 ||
- (b->tsorted && b->trevsorted &&
- n->tsorted && n->trevsorted &&
- ATOMcmp(b->ttype, BUNtail(bi, 0), BUNtail(ni, 0)) == 0)) {
- bat_iterator_end(&ni);
- return GDK_SUCCEED;
- }
-#endif
OIDXdestroy(b);
IMPSdestroy(b);
@@ -1204,8 +1219,13 @@ BATappend_or_update(BAT *b, BAT *p, BAT
b->theap->dirty = true;
if (b->tvarsized) {
b->tvheap->dirty = true;
- for (BUN i = 0, j = BATcount(p); i < j; i++) {
- oid updid = BUNtoid(p, i);
+ for (BUN i = 0; i < ni.count; i++) {
+ oid updid;
+ if (positions) {
+ updid = autoincr ? pos++ : *positions++;
+ } else {
+ updid = BUNtoid(p, i);
+ }
if (updid < b->hseqbase ||
(!mayappend && updid >= hseqend)) {
@@ -1350,8 +1370,13 @@ BATappend_or_update(BAT *b, BAT *p, BAT
}
} else if (ATOMstorage(b->ttype) == TYPE_msk) {
HASHdestroy(b); /* hash doesn't make sense for msk */
- for (BUN i = 0, j = BATcount(p); i < j; i++) {
- oid updid = BUNtoid(p, i);
+ for (BUN i = 0; i < ni.count; i++) {
+ oid updid;
+ if (positions) {
+ updid = autoincr ? pos++ : *positions++;
+ } else {
+ updid = BUNtoid(p, i);
+ }
if (updid < b->hseqbase ||
(!mayappend && updid >= hseqend)) {
@@ -1381,32 +1406,30 @@ BATappend_or_update(BAT *b, BAT *p, BAT
}
mskSetVal(b, updid, Tmskval(&ni, i));
}
- } else if (BATtdense(p)) {
- oid updid = BUNtoid(p, 0);
-
- if (updid < b->hseqbase ||
- (!mayappend && updid + BATcount(p) > hseqend)) {
+ } else if (autoincr) {
+ if (pos < b->hseqbase ||
+ (!mayappend && pos + ni.count > hseqend)) {
GDKerror("id out of range\n");
bat_iterator_end(&ni);
return GDK_FAIL;
}
- updid -= b->hseqbase;
- if (!force && updid < b->batInserted) {
+ pos -= b->hseqbase;
+ if (!force && pos < b->batInserted) {
GDKerror("updating committed value\n");
bat_iterator_end(&ni);
return GDK_FAIL;
}
- if (updid >= BATcount(b)) {
+ if (pos >= BATcount(b)) {
assert(mayappend);
bat_iterator_end(&ni);
- while (BATcount(b) < updid) {
+ while (BATcount(b) < pos) {
if (BUNappend(b, ATOMnilptr(b->ttype), force)
!= GDK_SUCCEED)
return GDK_FAIL;
}
return BATappend(b, n, NULL, force);
}
- while (updid + ni.count > BATcount(b)) {
+ while (pos + ni.count > BATcount(b)) {
if (BUNappend(b, ATOMnilptr(b->ttype), force) !=
GDK_SUCCEED) {
bat_iterator_end(&ni);
return GDK_FAIL;
@@ -1425,11 +1448,11 @@ BATappend_or_update(BAT *b, BAT *p, BAT
* in the first iteration, after which there is no hash
* and the loop ends */
MT_rwlock_wrlock(&b->thashlock);
- for (BUN i = updid, j = updid + BATcount(p); i < j && b->thash;
i++)
+ for (BUN i = pos, j = pos + ni.count; i < j && b->thash; i++)
HASHdelete_locked(b, i, Tloc(b, i));
if (n->ttype == TYPE_void) {
assert(b->ttype == TYPE_oid);
- oid *o = Tloc(b, updid);
+ oid *o = Tloc(b, pos);
if (is_oid_nil(ni.tseq)) {
/* we may or may not overwrite the old
* min/max values */
@@ -1437,7 +1460,7 @@ BATappend_or_update(BAT *b, BAT *p, BAT
BATrmprop(b, GDK_MIN_VALUE);
BATrmprop(b, GDK_MAX_POS);
BATrmprop(b, GDK_MIN_POS);
- for (BUN i = 0, j = BATcount(p); i < j; i++)
+ for (BUN i = 0, j = ni.count; i < j; i++)
o[i] = oid_nil;
b->tnil = true;
} else {
@@ -1447,16 +1470,16 @@ BATappend_or_update(BAT *b, BAT *p, BAT
* are smaller/larger than the old */
if (minprop && v <= minprop->val.oval) {
BATsetprop(b, GDK_MIN_VALUE, TYPE_oid,
&v);
- BATsetprop(b, GDK_MIN_POS, TYPE_oid,
&(oid){updid});
+ BATsetprop(b, GDK_MIN_POS, TYPE_oid,
&(oid){pos});
} else {
BATrmprop(b, GDK_MIN_VALUE);
BATrmprop(b, GDK_MIN_POS);
}
- for (BUN i = 0, j = BATcount(p); i < j; i++)
+ for (BUN i = 0, j = ni.count; i < j; i++)
o[i] = v++;
if (maxprop && --v >= maxprop->val.oval) {
BATsetprop(b, GDK_MAX_VALUE, TYPE_oid,
&v);
- BATsetprop(b, GDK_MAX_POS, TYPE_oid,
&(oid){updid + BATcount(p) - 1});
+ BATsetprop(b, GDK_MAX_POS, TYPE_oid,
&(oid){pos + ni.count - 1});
} else {
BATrmprop(b, GDK_MAX_VALUE);
BATrmprop(b, GDK_MAX_POS);
@@ -1473,7 +1496,7 @@ BATappend_or_update(BAT *b, BAT *p, BAT
atomcmp(VALptr(maxprop), VALptr(prop)) <= 0) {
BATsetprop(b, GDK_MAX_VALUE, b->ttype,
VALptr(prop));
if ((prop = BATgetprop(n, GDK_MAX_POS)) != NULL)
- BATsetprop(b, GDK_MAX_POS, TYPE_oid,
&(oid){prop->val.oval + updid});
+ BATsetprop(b, GDK_MAX_POS, TYPE_oid,
&(oid){prop->val.oval + pos});
else
BATrmprop(b, GDK_MAX_POS);
} else {
@@ -1485,26 +1508,26 @@ BATappend_or_update(BAT *b, BAT *p, BAT
atomcmp(VALptr(minprop), VALptr(prop)) >= 0) {
BATsetprop(b, GDK_MIN_VALUE, b->ttype,
VALptr(prop));
if ((prop = BATgetprop(n, GDK_MIN_POS)) != NULL)
- BATsetprop(b, GDK_MIN_POS, TYPE_oid,
&(oid){prop->val.oval + updid});
+ BATsetprop(b, GDK_MIN_POS, TYPE_oid,
&(oid){prop->val.oval + pos});
else
BATrmprop(b, GDK_MIN_POS);
} else {
BATrmprop(b, GDK_MIN_VALUE);
BATrmprop(b, GDK_MIN_POS);
}
- memcpy(Tloc(b, updid), ni.base,
- BATcount(p) * b->twidth);
+ memcpy(Tloc(b, pos), ni.base,
+ ni.count * b->twidth);
}
/* either we have a hash that was updated above, or we
* have no hash; we cannot have the case where there is
* only a persisted (unloaded) hash since it would have
* been destroyed above */
if (b->thash != NULL) {
- for (BUN i = updid, j = updid + BATcount(p); i < j; i++)
+ for (BUN i = pos, j = pos + ni.count; i < j; i++)
HASHinsert_locked(b, i, Tloc(b, i));
}
MT_rwlock_wrunlock(&b->thashlock);
- if (BATcount(p) == BATcount(b)) {
+ if (ni.count == BATcount(b)) {
/* if we replaced all values of b by values
* from n, we can also copy the min/max
* properties */
@@ -1530,8 +1553,14 @@ BATappend_or_update(BAT *b, BAT *p, BAT
}
}
} else {
- for (BUN i = 0, j = BATcount(p); i < j; i++) {
- oid updid = BUNtoid(p, i);
+ for (BUN i = 0, j = ni.count; i < j; i++) {
+ oid updid;
+ if (positions) {
+ /* assert(!autoincr) */
+ updid = *positions++;
+ } else {
+ updid = BUNtoid(p, i);
+ }
if (updid < b->hseqbase ||
(!mayappend && updid >= hseqend)) {
@@ -1659,14 +1688,29 @@ BATappend_or_update(BAT *b, BAT *p, BAT
gdk_return
BATreplace(BAT *b, BAT *p, BAT *n, bool force)
{
- return BATappend_or_update(b, p, n, false, force);
+ return BATappend_or_update(b, p, NULL, n, false, false, force);
}
/* like BATreplace, but p may specify locations beyond the end of b */
gdk_return
BATupdate(BAT *b, BAT *p, BAT *n, bool force)
{
- return BATappend_or_update(b, p, n, true, force);
+ return BATappend_or_update(b, p, NULL, n, true, false, force);
+}
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list