Changeset: 4d1315f86145 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=4d1315f86145
Added Files:
sql/test/BugTracker-2013/Tests/case_when.Bug-3395.sql
Modified Files:
clients/mapiclient/tomograph.c
gdk/gdk.h
gdk/gdk_aggr.c
gdk/gdk_atoms.c
gdk/gdk_bbp.c
gdk/gdk_calc.h
gdk/gdk_heap.c
gdk/gdk_utils.c
monetdb5/mal/mal_factory.c
monetdb5/mal/mal_instruction.c
monetdb5/mal/mal_instruction.h
monetdb5/mal/mal_profiler.c
monetdb5/mal/mal_readline.c
monetdb5/modules/kernel/aggr.c
monetdb5/modules/kernel/aggr.mal
monetdb5/modules/kernel/aggr.mal.sh
monetdb5/modules/mal/tablet.c
monetdb5/optimizer/opt_qep.c
sql/backends/monet5/gsl/Tests/gsl01.stable.err
sql/backends/monet5/gsl/Tests/gsl01.stable.out
sql/backends/monet5/gsl/gsl.c
sql/backends/monet5/sql.mx
sql/scripts/39_analytics.sql
sql/server/rel_dump.c
sql/test/BugTracker-2013/Tests/All
sql/test/BugTracker-2013/Tests/Cannot_Find_Column_Type.Bug-3394.sql
tools/merovingian/client/monetdb.c
Branch: default
Log Message:
Merger
diffs (truncated from 1476 to 300 lines):
diff --git a/clients/mapiclient/tomograph.c b/clients/mapiclient/tomograph.c
--- a/clients/mapiclient/tomograph.c
+++ b/clients/mapiclient/tomograph.c
@@ -2157,7 +2157,7 @@ doProfile(void *d)
for (i = 0; i < MAXTHREADS; i++)
threads[i] = topbox++;
- /* sent single query */
+ /* send single query */
if (sqlstatement) {
doRequest(dbhsql, sqlstatement);
}
diff --git a/gdk/gdk.h b/gdk/gdk.h
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -2275,7 +2275,7 @@ gdk_export str GDKstrdup(const char *s);
void *_res = GDKmmap(_path, _mode, _len); \
ALLOCDEBUG \
fprintf(stderr, \
- "#GDKmmap(%s,0x%x," SZFMT ") -> " SZFMT \
+ "#GDKmmap(%s,0x%x," SZFMT ") -> " PTRFMT \
" %s[%s:%d]\n", \
_path ? _path : "NULL", _mode, _len, \
PTRFMTCAST _res, \
diff --git a/gdk/gdk_aggr.c b/gdk/gdk_aggr.c
--- a/gdk/gdk_aggr.c
+++ b/gdk/gdk_aggr.c
@@ -2183,10 +2183,16 @@ BATmax(BAT *b, void *aggr)
/* ---------------------------------------------------------------------- */
-/* median */
+/* quantiles/median */
BAT *
-BATgroupmedian(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int skip_nils, int
abort_on_error)
+
+BATgroupmedian(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int skip_nils, int
abort_on_error) {
+ return BATgroupquantile(b,g,e,s,tp,0.5,skip_nils,abort_on_error);
+}
+
+BAT *
+ BATgroupquantile(BAT *b, BAT *g, BAT *e, BAT *s, int tp, double quantile,int
skip_nils, int abort_on_error)
{
int freeb = 0, freeg = 0;
oid min, max;
@@ -2201,20 +2207,23 @@ BATgroupmedian(BAT *b, BAT *g, BAT *e, B
const void *nil;
int (*atomcmp)(const void *, const void *);
const char *err;
-
(void) abort_on_error;
if ((err = BATgroupaggrinit(b, g, e, s, &min, &max, &ngrp, &start, &end,
&cnt, &cand, &candend)) != NULL) {
- GDKerror("BATgroupmedian: %s\n", err);
+ GDKerror("BATgroupquantile: %s\n", err);
return NULL;
}
assert(tp == b->ttype);
if (!ATOMlinear(b->ttype)) {
- GDKerror("BATgroupmedian: cannot determine median on "
+ GDKerror("BATgroupquantile: cannot determine quantile on "
"non-linear type %s\n", ATOMname(b->ttype));
return NULL;
}
+ if (quantile < 0 || quantile > 1) {
+ GDKerror("BATgroupquantile: cannot determine quantile for p=%f
(p has to be in [0,1])\n",quantile);
+ return NULL;
+ }
if (BATcount(b) == 0 || ngrp == 0) {
/* trivial: no medians, so return bat aligned with e with
@@ -2305,7 +2314,8 @@ BATgroupmedian(BAT *b, BAT *g, BAT *e, B
nil, 0, Tsize(bn));
nils++;
} else {
- v = BUNtail(bi, BUNfirst(b) + (r + p -
1) / 2);
+ // actual selection of quantile value
for groups
+ v = BUNtail(bi, (oid)( BUNfirst(b) + (r
+ p - 1) * quantile));
bunfastins_nocheck(bn, BUNlast(bn), 0,
v, 0, Tsize(bn));
nils += (*atomcmp)(v, nil) == 0;
@@ -2321,7 +2331,8 @@ BATgroupmedian(BAT *b, BAT *g, BAT *e, B
}
BATseqbase(bn, min);
} else {
- v = BUNtail(bi, BUNfirst(b) + (BATcount(b) - 1) / 2);
+ // actual selection of quantile value
+ v = BUNtail(bi, (oid) (BUNfirst(b) + (BATcount(b) - 1) *
quantile));
BUNappend(bn, v, FALSE);
BATseqbase(bn, 0);
nils += (*atomcmp)(v, nil) == 0;
diff --git a/gdk/gdk_atoms.c b/gdk/gdk_atoms.c
--- a/gdk/gdk_atoms.c
+++ b/gdk/gdk_atoms.c
@@ -963,6 +963,9 @@ strHash(const char *s)
return res;
}
+/* if at least (2*SIZEOF_BUN), also store length (heaps are then
+ * incompatible) */
+#define EXTRALEN ((SIZEOF_BUN + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1))
void
strCleanHash(Heap *h, int rebuild)
@@ -971,6 +974,50 @@ strCleanHash(Heap *h, int rebuild)
if (!GDK_ELIMDOUBLES(h)) {
/* flush hash table for security */
memset(h->base, 0, GDK_STRHASHSIZE);
+ } else {
+ /* rebuild hash table for double elimination
+ *
+ * If appending strings to the BAT was aborted, if the
+ * heap was memory mapped, the hash in the string heap
+ * may well be incorrect. Therefore we don't trust it
+ * when we read in a string heap and we rebuild the
+ * complete table (it is small, so this won't take any
+ * time at all). */
+ size_t pad, pos;
+ const size_t extralen = h->hashash ? EXTRALEN : 0;
+ stridx_t *bucket;
+ BUN off, strhash;
+ const char *s;
+
+ memset(h->base, 0, GDK_STRHASHSIZE);
+ pos = GDK_STRHASHSIZE;
+ while (pos < h->free) {
+ pad = GDK_VARALIGN - (pos & (GDK_VARALIGN - 1));
+ if (pad < sizeof(stridx_t))
+ pad += GDK_VARALIGN;
+ pos += pad + extralen;
+ s = h->base + pos;
+ if (h->hashash)
+ strhash = ((const BUN *) s)[-1];
+ else
+ GDK_STRHASH(s, strhash);
+ off = strhash & GDK_STRHASHMASK;
+ bucket = ((stridx_t *) h->base) + off;
+ *bucket = pos - extralen - sizeof(stridx_t);
+ pos += GDK_STRLEN(s);
+ }
+#ifndef NDEBUG
+ pos = GDK_STRHASHSIZE;
+ while (pos < h->free) {
+ pad = GDK_VARALIGN - (pos & (GDK_VARALIGN - 1));
+ if (pad < sizeof(stridx_t))
+ pad += GDK_VARALIGN;
+ pos += pad + extralen;
+ s = h->base + pos;
+ assert(strLocate(h, s) != 0);
+ pos += GDK_STRLEN(s);
+ }
+#endif
}
}
@@ -979,15 +1026,11 @@ strCleanHash(Heap *h, int rebuild)
* the location of a string in the heap if it exists. Otherwise it
* returns zero.
*/
-/* if at least (2*SIZEOF_BUN), also store length (heaps are then
- * incompatible) */
-#define EXTRALEN ((SIZEOF_BUN + GDK_VARALIGN - 1) & ~(GDK_VARALIGN - 1))
-
var_t
strLocate(Heap *h, const char *v)
{
stridx_t *ref, *next;
- size_t extralen = h->hashash ? EXTRALEN : 0;
+ const size_t extralen = h->hashash ? EXTRALEN : 0;
/* search hash-table, if double-elimination is still in place */
BUN off;
@@ -1012,7 +1055,7 @@ strPut(Heap *h, var_t *dst, const char *
size_t elimbase = GDK_ELIMBASE(h->free);
size_t pad = GDK_VARALIGN - (h->free & (GDK_VARALIGN - 1));
size_t pos, len = GDK_STRLEN(v);
- size_t extralen = h->hashash ? EXTRALEN : 0;
+ const size_t extralen = h->hashash ? EXTRALEN : 0;
stridx_t *bucket, *ref, *next;
BUN off, strhash;
@@ -1021,24 +1064,30 @@ strPut(Heap *h, var_t *dst, const char *
off &= GDK_STRHASHMASK;
bucket = ((stridx_t *) h->base) + off;
- /* search hash-table, if double-elimination is still in place */
- if (elimbase == 0) { /* small string heap (<64KB) -- fully double
eliminated */
- for (ref = bucket; *ref; ref = next) { /* search the linked
list */
+ /* if double-elimination is still in place, search hash-table */
+ if (elimbase == 0) {
+ /* small string heap (<64KB) -- fully double eliminated */
+ for (ref = bucket; *ref; ref = next) {
+ /* search the linked list */
next = (stridx_t *) (h->base + *ref);
- if (GDK_STRCMP(v, (str) (next + 1) + extralen) == 0) {
/* found */
+ if (GDK_STRCMP(v, (str) (next + 1) + extralen) == 0) {
+ /* found */
pos = sizeof(stridx_t) + *ref + extralen;
return *dst = (var_t) (pos >> GDK_VARSHIFT);
}
}
/* is there room for the next pointer in the padding space? */
- if (pad < sizeof(stridx_t))
- pad += GDK_VARALIGN; /* if not, pad more */
+ if (pad < sizeof(stridx_t)) {
+ /* if not, pad more */
+ pad += GDK_VARALIGN;
+ }
} else if (*bucket) {
/* large string heap (>=64KB) --
* opportunistic/probabilistic double elimination */
pos = elimbase + *bucket + extralen;
if (GDK_STRCMP(v, h->base + pos) == 0) {
- return *dst = (var_t) (pos >> GDK_VARSHIFT); /*
already in heap; do not insert! */
+ /* already in heap; do not insert! */
+ return *dst = (var_t) (pos >> GDK_VARSHIFT);
}
#if SIZEOF_VAR_T >= SIZEOF_VOID_P /* in fact SIZEOF_VAR_T == SIZEOF_VOID_P */
if (extralen == 0)
diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -3165,8 +3165,14 @@ do_backup(const char *srcdir, const char
int ret = 0;
/* direct mmap is unprotected (readonly usage, or has WAL
- * protection) */
- if (h->storage != STORE_MMAP) {
+ * protection); however, if we're backing up for subcommit
+ * and a backup already exists in the main backup directory
+ * (see GDKupgradevarheap), move the file */
+ if (subcommit && file_exists(BAKDIR, nme, extbase)) {
+ assert(h->storage == STORE_MMAP);
+ if (file_move(BAKDIR, SUBDIR, nme, extbase))
+ return -1;
+ } else if (h->storage != STORE_MMAP) {
/* STORE_PRIV saves into X.new files. Two cases could
* happen. The first is when a valid X.new exists
* because of an access change or a previous
diff --git a/gdk/gdk_calc.h b/gdk/gdk_calc.h
--- a/gdk/gdk_calc.h
+++ b/gdk/gdk_calc.h
@@ -126,6 +126,8 @@ gdk_export BAT *BATgroupsize(BAT *b, BAT
gdk_export BAT *BATgroupmin(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int
skip_nils, int abort_on_error);
gdk_export BAT *BATgroupmax(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int
skip_nils, int abort_on_error);
gdk_export BAT *BATgroupmedian(BAT *b, BAT *g, BAT *e, BAT *s, int tp, int
skip_nils, int abort_on_error);
+gdk_export BAT *BATgroupquantile(BAT *b, BAT *g, BAT *e, BAT *s, int tp,
double quantile, int skip_nils, int abort_on_error);
+
/* helper function for grouped aggregates */
gdk_export const char *BATgroupaggrinit(
const BAT *b, const BAT *g, const BAT *e, const BAT *s,
diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c
--- a/gdk/gdk_heap.c
+++ b/gdk/gdk_heap.c
@@ -390,6 +390,20 @@ HEAPshrink(Heap *h, size_t size)
return -1;
}
+/* returns 1 if the file exists */
+static int
+file_exists(const char *dir, const char *name, const char *ext)
+{
+ long_str path;
+ struct stat st;
+ int ret;
+
+ GDKfilepath(path, dir, name, ext);
+ ret = stat(path, &st);
+ IODEBUG THRprintf(GDKstdout, "#stat(%s) = %d\n", path, ret);
+ return (ret == 0);
+}
+
int
GDKupgradevarheap(COLrec *c, var_t v, int copyall)
{
@@ -403,6 +417,7 @@ GDKupgradevarheap(COLrec *c, var_t v, in
#endif
size_t i, n;
size_t savefree;
+ const char *filename;
assert(c->heap.parentid == 0);
assert(width != 0);
@@ -414,11 +429,65 @@ GDKupgradevarheap(COLrec *c, var_t v, in
}
assert(c->width < width);
assert(c->shift < shift);
+
/* if copyall is set, we need to convert the whole heap, since
* we may be in the middle of an insert loop that adjusts the
* free value at the end; otherwise only copy the area
* indicated by the "free" pointer */
n = (copyall ? c->heap.size : c->heap.free) >> c->shift;
+
+ /* for memory mapped files, create a backup copy before widening
+ *
+ * this solves a problem that we don't control what's in the
+ * actual file until the next commit happens, so a crash might
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list