changeset 83708:090dbb58aec7 directappend

Merge branch 'default' into 'directappend'
author Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com>
date Tue, 23 Nov 2021 09:46:46 +0100
parents a823bd637db2 (current diff) bf98880283b0 (diff)
children 3d607e308291
files sql/backends/monet5/sql.c sql/backends/monet5/sql_result.c
diffstat 61 files changed, 755 insertions(+), 287 deletions(-) [+]
line wrap: on
line diff
--- a/clients/mapiclient/dump.c
+++ b/clients/mapiclient/dump.c
@@ -1506,15 +1506,15 @@ describe_sequence(Mapi mid, const char *
 		goto bailout;
 
 	snprintf(query, maxquerylen,
-		"SELECT s.name, "							/* 0 */
-		       "seq.name, "							/* 1 */
-		       "get_value_for(s.name, seq.name), "	/* 2 */
-		       "seq.\"minvalue\", "					/* 3 */
-		       "seq.\"maxvalue\", "					/* 4 */
-		       "seq.\"increment\", "				/* 5 */
-		       "seq.\"cycle\", "					/* 6 */
-		       "seq.\"cacheinc\", "					/* 7 */
-		       "rem.\"remark\" "					/* 8 */
+		"SELECT s.name, "									/* 0 */
+		       "seq.name, "									/* 1 */
+		       "peak_next_value_for(s.name, seq.name), "	/* 2 */
+		       "seq.\"minvalue\", "							/* 3 */
+		       "seq.\"maxvalue\", "							/* 4 */
+		       "seq.\"increment\", "						/* 5 */
+		       "seq.\"cycle\", "							/* 6 */
+		       "seq.\"cacheinc\", "							/* 7 */
+		       "rem.\"remark\" "							/* 8 */
 		"FROM sys.sequences seq LEFT OUTER JOIN sys.comments rem ON seq.id = rem.id, "
 		     "sys.schemas s "
 		"WHERE s.id = seq.schema_id "
--- a/gdk/CMakeLists.txt
+++ b/gdk/CMakeLists.txt
@@ -18,6 +18,7 @@ set(gdk_public_headers
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gdk_utils.h>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gdk_cand.h>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gdk_calc.h>
+  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gdk_strimps.h>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/gdk_time.h>
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk.h>
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk_system.h>
@@ -30,6 +31,7 @@ set(gdk_public_headers
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk_utils.h>
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk_calc.h>
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk_cand.h>
+  $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk_strimps.h>
   $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/monetdb/gdk_time.h>)
 
 add_library(bat SHARED)
@@ -81,7 +83,7 @@ target_sources(bat
   gdk_analytic_func.c
   gdk_analytic.h
   gdk_tracer.c gdk_tracer.h
-  gdk_strimps.c gdk_strimps.h
+  gdk_strimps.c
   PUBLIC
   ${gdk_public_headers})
 
--- a/gdk/gdk_strimps.c
+++ b/gdk/gdk_strimps.c
@@ -297,16 +297,18 @@ STRMPbuildHeader(BAT *b, BAT *s, CharPai
 	CharPair cp, *cpp;
 	struct canditer ci;
 	size_t values = 0;
-
+	bool res;
 
 	TRC_DEBUG_IF(ACCELERATOR) t0 = GDKusec();
-	hlen = STRIMP_HISTSIZE;
-	if ((hist = (PairHistogramElem *)GDKmalloc(hlen*sizeof(PairHistogramElem))) == NULL) {
+
+	ncand = canditer_init(&ci, b, s);
+	if (ncand == 0) {
+		GDKerror("Not enough distinct values to create strimp index\n");
 		return false;
 	}
 
-	ncand = canditer_init(&ci, b, s);
-	if (ncand == 0) {
+	hlen = STRIMP_HISTSIZE;
+	if ((hist = (PairHistogramElem *)GDKmalloc(hlen*sizeof(PairHistogramElem))) == NULL) {
 		return false;
 	}
 
@@ -357,6 +359,13 @@ STRMPbuildHeader(BAT *b, BAT *s, CharPai
 					if (hist[hidx].p == NULL) {
 						values++;
 						hist[hidx].p = (CharPair *)GDKmalloc(sizeof(CharPair));
+						if (!hist[hidx].p) {
+							bat_iterator_end(&bi);
+							for (hidx = 0; hidx < hlen; hidx++)
+								GDKfree(hist[hidx].p);
+							GDKfree(hist);
+							return false;
+						}
 						hist[hidx].p->psize = cpp->psize;
 						hist[hidx].p->pbytes = cpp->pbytes;
 					}
@@ -382,7 +391,9 @@ STRMPbuildHeader(BAT *b, BAT *s, CharPai
 	GDKfree(hist);
 
 	TRC_DEBUG(ACCELERATOR, LLFMT " usec\n", GDKusec() - t0);
-	return values >= STRIMP_HEADER_SIZE;
+	if (!(res = values >= STRIMP_HEADER_SIZE))
+		GDKerror("Not enough distinct values to create strimp index\n");
+	return res;
 }
 
 static bool
@@ -480,6 +491,16 @@ BATcheckstrimps(BAT *b)
 	return ret;
 }
 
+#define STRMPfilterloop(next) \
+	do { \
+		for (i = 0; i < ncand; i++) { \
+			x = next(&ci); \
+			if ((bitstring_array[x] & qbmask) == qbmask) { \
+				rvals[j++] = x; \
+			} \
+		} \
+	} while (0)
+
 /* Filter a BAT b using a string q. Return the result as a candidate
  * list.
  */
@@ -487,11 +508,11 @@ BAT *
 STRMPfilter(BAT *b, BAT *s, const str q)
 {
 	BAT *r = NULL;
-	BUN i, ncand;
+	BUN i, ncand, j = 0;
 	uint64_t qbmask;
 	uint64_t *bitstring_array;
 	Strimps *strmps;
-	oid x;
+	oid x, *restrict rvals;
 	struct canditer ci;
 	lng t0 = 0;
 	BAT *pb;
@@ -512,7 +533,7 @@ STRMPfilter(BAT *b, BAT *s, const str q)
 	STRMPincref(strmps);
 	MT_lock_unset(&pb->batIdxLock);
 
-        ncand = canditer_init(&ci, b, s);
+	ncand = canditer_init(&ci, b, s);
 	if (ncand == 0) {
 		STRMPdecref(strmps, false);
 		return BATdense(b->hseqbase, 0, 0);
@@ -525,18 +546,15 @@ STRMPfilter(BAT *b, BAT *s, const str q)
 
 	qbmask = STRMPmakebitstring(q, strmps);
 	bitstring_array = (uint64_t *)strmps->bitstrings_base;
+	rvals = Tloc(r, 0);
 
-	for (i = 0; i < ncand; i++) {
-		x = canditer_next(&ci);
-		if ((bitstring_array[x] & qbmask) == qbmask) {
-			if (BUNappend(r, &x, false) != GDK_SUCCEED) {
-				BBPunfix(r->batCacheid);
-				STRMPdecref(strmps, false);
-				goto sfilter_fail;
-			}
-		}
+	if (ci.tpe == cand_dense) {
+		STRMPfilterloop(canditer_next_dense);
+	} else {
+		STRMPfilterloop(canditer_next);
 	}
 
+	BATsetcount(r, j);
 	r->tkey = true;
 	r->tsorted = true;
 	r->trevsorted = BATcount(r) <= 1;
@@ -636,8 +654,8 @@ STRMPcreateStrimpHeap(BAT *b, BAT *s)
 	CharPair hpairs[STRIMP_HEADER_SIZE];
 	const char *nme;
 
-        if ((r = b->tstrimps) == NULL &&
-	    STRMPbuildHeader(b, s, hpairs)) { /* Find the header pairs, put
+	if ((r = b->tstrimps) == NULL &&
+		STRMPbuildHeader(b, s, hpairs)) { /* Find the header pairs, put
 						 the result in hpairs */
 		sz = 8 + STRIMP_HEADER_SIZE; /* add 8-bytes for the descriptor and
 						the pair sizes */
@@ -707,7 +725,7 @@ STRMPcreate(BAT *b, BAT *s)
 
 	if (pb->tstrimps == NULL) {
 		MT_lock_set(&pb->batIdxLock);
-                if (pb->tstrimps == NULL) {
+		if (pb->tstrimps == NULL) {
 			Strimps *r;
 			BATiter bi;
 			BUN i, ncand;
@@ -716,10 +734,10 @@ STRMPcreate(BAT *b, BAT *s)
 			str cs;
 			uint64_t *dh;
 
-                        if ((r = STRMPcreateStrimpHeap(pb, s)) == NULL) {
-                                MT_lock_unset(&b->batIdxLock);
+			if ((r = STRMPcreateStrimpHeap(pb, s)) == NULL) {
+				MT_lock_unset(&pb->batIdxLock);
 				return GDK_FAIL;
-                        }
+			}
 			dh = (uint64_t *)r->bitstrings_base;
 
 			/* Compute bitstrings */
@@ -739,10 +757,10 @@ STRMPcreate(BAT *b, BAT *s)
 			pb->tstrimps = r;
 			pb->batDirtydesc = true;
 			persistStrimp(pb);
-                }
-                MT_lock_unset(&pb->batIdxLock);
-        }
-        TRC_DEBUG(ACCELERATOR, "strimp creation took " LLFMT " usec\n", GDKusec()-t0);
+		}
+		MT_lock_unset(&pb->batIdxLock);
+	}
+	TRC_DEBUG(ACCELERATOR, "strimp creation took " LLFMT " usec\n", GDKusec()-t0);
 	return GDK_SUCCEED;
 }
 
@@ -780,6 +798,7 @@ STRMPappendBitstring(BAT *b, const str s
 		size_t pairs_offset = (char *)strmp->pairs_base - strmp->strimps.base;
 		size_t bitstrings_offset = (char *)strmp->bitstrings_base - strmp->strimps.base;
 		if (HEAPextend(&(strmp->strimps), (size_t)(extend_factor*BATcount(pb)*sizeof(uint64_t)), false) == GDK_FAIL) {
+			MT_lock_unset(&pb->batIdxLock);
 			GDKerror("Cannot extend heap\n");
 			return GDK_FAIL;
 		}
--- a/geom/monetdb5/geom.c
+++ b/geom/monetdb5/geom.c
@@ -5799,10 +5799,9 @@ pnpoly(int *out, int nvert, dbl *vx, dbl
 	}
 	bat_iterator_end(&bpxi);
 	bat_iterator_end(&bpyi);
-
+	BATsetcount(bo, cnt);
 	bo->tsorted = bo->trevsorted = false;
 	bo->tkey = false;
-	BATsetcount(bo, cnt);
 	BBPunfix(bpx->batCacheid);
 	BBPunfix(bpy->batCacheid);
 	BBPkeepref(*out = bo->batCacheid);
@@ -5892,9 +5891,9 @@ pnpolyWithHoles(bat *out, int nvert, dbl
 	}
 	bat_iterator_end(&bpxi);
 	bat_iterator_end(&bpyi);
+	BATsetcount(bo, cnt);
 	bo->tsorted = bo->trevsorted = false;
 	bo->tkey = false;
-	BATsetcount(bo, cnt);
 	BBPunfix(bpx->batCacheid);
 	BBPunfix(bpy->batCacheid);
 	BBPkeepref(*out = bo->batCacheid);
--- a/monetdb5/modules/atoms/json.c
+++ b/monetdb5/modules/atoms/json.c
@@ -1230,6 +1230,9 @@ static str
 JSONfilterArrayDefault(json *ret, json *js, lng index, str other)
 {
 	char expr[BUFSIZ], *s = expr;
+
+	if (index < 0)
+		throw(MAL,"json.filter", SQLSTATE(42000) "Filter index cannot be negative");
 	snprintf(expr, BUFSIZ, "[" LLFMT "]", index);
 	return JSONfilterInternal(ret, js, &s, other);
 }
@@ -1237,48 +1240,88 @@ JSONfilterArrayDefault(json *ret, json *
 static str
 JSONfilterArray_bte(json *ret, json *js, bte *index)
 {
+	if (strNil(*js) || is_bte_nil(*index)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, 0);
 }
 
 static str
 JSONfilterArrayDefault_bte(json *ret, json *js, bte *index, str *other)
 {
+	if (strNil(*js) || is_bte_nil(*index) || strNil(*other)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, *other);
 }
 
 static str
 JSONfilterArray_sht(json *ret, json *js, sht *index)
 {
+	if (strNil(*js) || is_sht_nil(*index)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, 0);
 }
 
 static str
 JSONfilterArrayDefault_sht(json *ret, json *js, sht *index, str *other)
 {
+	if (strNil(*js) || is_sht_nil(*index) || strNil(*other)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, *other);
 }
 
 static str
 JSONfilterArray_int(json *ret, json *js, int *index)
 {
+	if (strNil(*js) || is_int_nil(*index)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, 0);
 }
 
 static str
 JSONfilterArrayDefault_int(json *ret, json *js, int *index, str *other)
 {
+	if (strNil(*js) || is_int_nil(*index) || strNil(*other)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, *other);
 }
 
 static str
 JSONfilterArray_lng(json *ret, json *js, lng *index)
 {
+	if (strNil(*js) || is_lng_nil(*index)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, 0);
 }
 
 static str
 JSONfilterArrayDefault_lng(json *ret, json *js, lng *index, str *other)
 {
+	if (strNil(*js) || is_lng_nil(*index) || strNil(*other)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterArrayDefault(ret, js, (lng) *index, *other);
 }
 
@@ -1286,6 +1329,11 @@ JSONfilterArrayDefault_lng(json *ret, js
 static str
 JSONfilterArray_hge(json *ret, json *js, hge *index)
 {
+	if (strNil(*js) || is_hge_nil(*index)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	if (*index < (hge) GDK_lng_min || *index > (hge) GDK_lng_max)
 		throw(MAL, "json.filter", "index out of range");
 	return JSONfilterArrayDefault(ret, js, (lng) *index, 0);
@@ -1294,6 +1342,11 @@ JSONfilterArray_hge(json *ret, json *js,
 static str
 JSONfilterArrayDefault_hge(json *ret, json *js, hge *index, str *other)
 {
+	if (strNil(*js) || is_hge_nil(*index) || strNil(*other)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	if (*index < (hge) GDK_lng_min || *index > (hge) GDK_lng_max)
 		throw(MAL, "json.filter", "index out of range");
 	return JSONfilterArrayDefault(ret, js, (lng) *index, *other);
@@ -1303,6 +1356,11 @@ JSONfilterArrayDefault_hge(json *ret, js
 static str
 JSONfilter(json *ret, json *js, str *expr)
 {
+	if (strNil(*js) || strNil(*expr)) {
+		if (!(*ret = GDKstrdup(str_nil)))
+			throw(MAL,"json.filter", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+		return MAL_SUCCEED;
+	}
 	return JSONfilterInternal(ret, js, expr, 0);
 }
 
--- a/monetdb5/modules/atoms/mtime.c
+++ b/monetdb5/modules/atoms/mtime.c
@@ -181,9 +181,9 @@ NAME##_bulk(Client cntxt, MalBlkPtr mb, 
 			nils |= is_##OUTTYPE##_nil(ptrn[i]);						\
 		}																\
 	}																	\
+	BATsetcount(bn, n);													\
 	bn->tnonil = !nils;													\
 	bn->tnil = nils;													\
-	BATsetcount(bn, n);													\
 	SETFLAGS;															\
 	bn->tkey = false;													\
 bailout: 																\
@@ -297,9 +297,9 @@ NAME##_bulk(Client cntxt, MalBlkPtr mb, 
 			nils |= is_##OUTTYPE##_nil(res);							\
 		}																\
 	}																	\
+	BATsetcount(bn, n);													\
 	bn->tnonil = !nils;													\
 	bn->tnil = nils;													\
-	BATsetcount(bn, n);													\
 	bn->tsorted = n < 2;												\
 	bn->trevsorted = n < 2;												\
 	bn->tkey = false;													\
@@ -378,9 +378,9 @@ NAME##_bulk_p1(Client cntxt, MalBlkPtr m
 			nils |= is_##OUTTYPE##_nil(res);							\
 		}																\
 	}																	\
+	BATsetcount(bn, n);													\
 	bn->tnonil = !nils;													\
 	bn->tnil = nils;													\
-	BATsetcount(bn, n);													\
 	bn->tsorted = n < 2;												\
 	bn->trevsorted = n < 2;												\
 	bn->tkey = false;													\
@@ -455,9 +455,9 @@ NAME##_bulk_p2(Client cntxt, MalBlkPtr m
 			nils |= is_##OUTTYPE##_nil(res);							\
 		}																\
 	}																	\
+	BATsetcount(bn, n);													\
 	bn->tnonil = !nils;													\
 	bn->tnil = nils;													\
-	BATsetcount(bn, n);													\
 	bn->tsorted = n < 2;												\
 	bn->trevsorted = n < 2;												\
 	bn->tkey = false;													\
--- a/monetdb5/modules/atoms/str.c
+++ b/monetdb5/modules/atoms/str.c
@@ -2931,18 +2931,18 @@ STRprelude(void *ret)
 			fp[i] = UTF8_toUpper[i].from;
 			tp[i] = UTF8_toUpper[i].to;
 		}
+		BATsetcount(UTF8_toUpperFrom, i);
 		UTF8_toUpperFrom->tkey = true;
 		UTF8_toUpperFrom->tsorted = true;
 		UTF8_toUpperFrom->trevsorted = false;
 		UTF8_toUpperFrom->tnil = false;
 		UTF8_toUpperFrom->tnonil = true;
-		BATsetcount(UTF8_toUpperFrom, i);
+		BATsetcount(UTF8_toUpperTo, i);
 		UTF8_toUpperTo->tkey = false;
 		UTF8_toUpperTo->tsorted = false;
 		UTF8_toUpperTo->trevsorted = false;
 		UTF8_toUpperTo->tnil = false;
 		UTF8_toUpperTo->tnonil = true;
-		BATsetcount(UTF8_toUpperTo, i);
 
 		fp = (int *) Tloc(UTF8_toLowerFrom, 0);
 		tp = (int *) Tloc(UTF8_toLowerTo, 0);
@@ -2950,18 +2950,18 @@ STRprelude(void *ret)
 			fp[i] = UTF8_toLower[i].from;
 			tp[i] = UTF8_toLower[i].to;
 		}
+		BATsetcount(UTF8_toLowerFrom, i);
 		UTF8_toLowerFrom->tkey = true;
 		UTF8_toLowerFrom->tsorted = true;
 		UTF8_toLowerFrom->trevsorted = false;
 		UTF8_toLowerFrom->tnil = false;
 		UTF8_toLowerFrom->tnonil = true;
-		BATsetcount(UTF8_toLowerFrom, i);
+		BATsetcount(UTF8_toLowerTo, i);
 		UTF8_toLowerTo->tkey = false;
 		UTF8_toLowerTo->tsorted = false;
 		UTF8_toLowerTo->trevsorted = false;
 		UTF8_toLowerTo->tnil = false;
 		UTF8_toLowerTo->tnonil = true;
-		BATsetcount(UTF8_toLowerTo, i);
 
 		if (BBPrename(UTF8_toUpperFrom->batCacheid, "monet_unicode_upper_from") != 0 ||
 			BBPrename(UTF8_toUpperTo->batCacheid, "monet_unicode_upper_to") != 0 ||
--- a/monetdb5/modules/atoms/uuid.c
+++ b/monetdb5/modules/atoms/uuid.c
@@ -136,9 +136,9 @@ UUIDgenerateUuidInt_bulk(Client cntxt, M
 	bnt = Tloc(bn, 0);
 	for (BUN i = 0 ; i < n ; i++)
 		UUIDgenerateUuid_internal(&(bnt[i]));
+	BATsetcount(bn, n);
 	bn->tnonil = true;
 	bn->tnil = false;
-	BATsetcount(bn, n);
 	bn->tsorted = n <= 1;
 	bn->trevsorted = n <= 1;
 	bn->tkey = n <= 1;
@@ -181,9 +181,9 @@ UUIDisaUUID_bulk(bat *ret, const bat *bi
 	for (BUN p = 0 ; p < q ; p++)
 		dst[p] = isaUUID(BUNtvar(bi, p));
 	bat_iterator_end(&bi);
+	BATsetcount(bn, q);
 	bn->tnonil = b->tnonil;
 	bn->tnil = b->tnil;
-	BATsetcount(bn, q);
 	bn->tsorted = bn->trevsorted = q < 2;
 	bn->tkey = false;
 bailout:
--- a/monetdb5/modules/mal/pcre.c
+++ b/monetdb5/modules/mal/pcre.c
@@ -1870,7 +1870,7 @@ PCRElikeselect(bat *ret, const bat *bid,
 	str msg = MAL_SUCCEED;
 	char *ppat = NULL;
 	bool use_re = false, use_strcmp = false, empty = false;
-	bool use_strimps = !GDKgetenv_istext("gdk_use_strimps", "no");
+	bool use_strimps = !GDKgetenv_istext("gdk_use_strimps", "no"), with_strimps = false;
 
 	if ((b = BATdescriptor(*bid)) == NULL) {
 		msg = createException(MAL, "algebra.likeselect", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
@@ -1883,6 +1883,9 @@ PCRElikeselect(bat *ret, const bat *bid,
 
 	assert(ATOMstorage(b->ttype) == TYPE_str);
 
+	if ((msg = choose_like_path(&ppat, &use_re, &use_strcmp, &empty, pat, esc)) != MAL_SUCCEED)
+		goto bailout;
+
 	/* Since the strimp pre-filtering of a LIKE query produces a superset of
 	 * the actual result the complement of that set will necessarily reject
 	 * some of the matching entries in the NOT LIKE query.
@@ -1890,23 +1893,22 @@ PCRElikeselect(bat *ret, const bat *bid,
 	 * A better solution is to run the PCRElikeselect as a LIKE query with
 	 * strimps and return the complement of the result.
 	 */
-	if (use_strimps && BATcount(b) >= STRIMP_CREATION_THRESHOLD && !*anti) {
-		if (STRMPcreate(b, NULL) == GDK_SUCCEED) {
-			BAT *tmp_s;
-			tmp_s = STRMPfilter(b, s, *pat);
-			if (tmp_s && s) {
+	if (!empty && use_strimps && BATcount(b) >= STRIMP_CREATION_THRESHOLD && !*anti) {
+		BAT *tmp_s = NULL;
+		if (STRMPcreate(b, NULL) == GDK_SUCCEED && (tmp_s = STRMPfilter(b, s, *pat))) {
+			if (s)
 				BBPunfix(s->batCacheid);
-				s = tmp_s;
-			}
-		} /* If we cannot create the strimp just continue normally */
-
+			s = tmp_s;
+			with_strimps = true;
+		} else { /* If we cannot create the strimp just continue normally */
+			GDKclrerr();
+		}
 	}
 
-	if ((msg = choose_like_path(&ppat, &use_re, &use_strcmp, &empty, pat, esc)) != MAL_SUCCEED)
-		goto bailout;
-
-	MT_thread_setalgorithm(empty ? "pcrelike: trivially empty" : use_strcmp ? "pcrelike: pattern matching using strcmp" :
-						   use_re ? "pcrelike: pattern matching using RE" : "pcrelike: pattern matching using pcre");
+	MT_thread_setalgorithm(empty ? "pcrelike: trivially empty" :
+		use_strcmp ? (with_strimps ? "pcrelike: pattern matching using strcmp with strimps" : "pcrelike: pattern matching using strcmp") :
+		use_re ? (with_strimps ? "pcrelike: pattern matching using RE with strimps" : "pcrelike: pattern matching using RE") :
+		(with_strimps ? "pcrelike: pattern matching using pcre with strimps" : "pcrelike: pattern matching using pcre"));
 
 	if (empty) {
 		if (!(bn = BATdense(0, 0, 0)))
@@ -1946,6 +1948,8 @@ PCRElikeselect(bat *ret, const bat *bid,
 			bn->tsorted = true;
 			bn->trevsorted = bn->batCount <= 1;
 			bn->tkey = true;
+			bn->tnil = false;
+			bn->tnonil = true;
 			bn->tseqbase = rcnt == 0 ? 0 : rcnt == 1 || rcnt == b->batCount ? b->hseqbase : oid_nil;
 		}
 	}
@@ -2138,10 +2142,14 @@ pcrejoin(BAT *r1, BAT *r2, BAT *l, BAT *
 	r1->tkey = true;
 	r1->tsorted = true;
 	r1->trevsorted = true;
+	r1->tnil = false;
+	r1->tnonil = true;
 	if (r2) {
 		r2->tkey = true;
 		r2->tsorted = true;
 		r2->trevsorted = true;
+		r2->tnil = false;
+		r2->tnonil = true;
 	}
 
 	if (anti) {
--- a/monetdb5/modules/mal/strimps.c
+++ b/monetdb5/modules/mal/strimps.c
@@ -80,7 +80,9 @@ static str
 PATstrimpCreate(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
 	bat bid, sid;
-	BAT *b, *s;
+	BAT *b, *s = NULL;
+	gdk_return res;
+
 	(void)cntxt;
 	(void)mb;
 
@@ -89,11 +91,17 @@ PATstrimpCreate(Client cntxt, MalBlkPtr 
 		throw(MAL, "strimps.strimpCreate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
 
 	sid = *getArgReference_bat(stk, pci, 2);
-	if ((s = BATdescriptor(sid)) == NULL)
+	if (sid && !is_bat_nil(sid) && (s = BATdescriptor(sid)) == NULL) {
+		BBPunfix(b->batCacheid);
 		throw(MAL, "strimps.strimpCreate", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
+	}
 
-	if(STRMPcreate(b, s) != GDK_SUCCEED)
-		throw(MAL, "strimps.strimpCreate", SQLSTATE(HY002) OPERATION_FAILED);
+	res = STRMPcreate(b, s);
+	BBPunfix(b->batCacheid);
+	if (s)
+		BBPunfix(s->batCacheid);
+	if (res != GDK_SUCCEED)
+		throw(MAL, "strimps.strimpCreate", GDK_EXCEPTION);
 
 	// *getArgReference_lng(stk, pci, 0) = 0;
 	return MAL_SUCCEED;
@@ -112,7 +120,7 @@ static str
 PATstrimpFilterSelect(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
 	bat bid, sid;
-	BAT *b, *s, *ob;
+	BAT *b, *s = NULL, *ob;
 	str pat;
 
 	(void)cntxt;
@@ -123,19 +131,27 @@ PATstrimpFilterSelect(Client cntxt, MalB
 		throw(MAL, "strimps.strimpfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
 
 	sid = *getArgReference_bat(stk, pci, 2);
-	if ((s = BATdescriptor(sid)) == NULL)
+	if (sid && !is_bat_nil(sid) && (s = BATdescriptor(sid)) == NULL) {
+		BBPunfix(b->batCacheid);
 		throw(MAL, "strimps.strimpfilter", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
+	}
+
+	assert(!s || s->ttype == TYPE_void);
 
-	assert(s->ttype == TYPE_void);
-
-	if(STRMPcreate(b, s) != GDK_SUCCEED)
-		throw(MAL, "strimps.strimpfilter", SQLSTATE(HY002) "strimp creation failed");
+	if (STRMPcreate(b, s) != GDK_SUCCEED) {
+		BBPunfix(b->batCacheid);
+		if (s)
+			BBPunfix(s->batCacheid);
+		throw(MAL, "strimps.strimpfilter", GDK_EXCEPTION);
+	}
 
 	pat = *getArgReference_str(stk, pci, 3);
-	if ((ob = STRMPfilter(b, s, pat)) == NULL) {
-		BBPunfix(b->batCacheid);
-		throw(MAL, "strimps.strimpfilter", SQLSTATE(HY002) "filtering failed");
-	}
+	ob = STRMPfilter(b, s, pat);
+	BBPunfix(b->batCacheid);
+	if (s)
+		BBPunfix(s->batCacheid);
+	if (ob == NULL)
+		throw(MAL, "strimps.strimpfilter", GDK_EXCEPTION);
 
 	*getArgReference_bat(stk, pci, 0) = ob->batCacheid;
 	BBPkeepref(ob->batCacheid);
--- a/monetdb5/optimizer/opt_for.c
+++ b/monetdb5/optimizer/opt_for.c
@@ -117,7 +117,7 @@ OPTforImplementation(Client cntxt, MalBl
 					freeInstruction(p);
 					done = 1;
 					break;
-				} else if (isSelect(p)) {
+				//} else if (isSelect(p)) {
 				} else// if (isSelect(p)) {
 					if (getFunctionId(p) == thetaselectRef) {
 						/* pos = thetaselect(col, cand, l, ...) with col = for.decompress(o, minval)
--- a/monetdb5/optimizer/opt_strimps.c
+++ b/monetdb5/optimizer/opt_strimps.c
@@ -27,8 +27,6 @@ OPTstrimpsImplementation(Client cntxt, M
 	bool needed = false;
 	// int mvcvar = -1;
 	InstrPtr p, q, *old = mb->stmt;
-	char buf[256];
-	lng usec = GDKusec();
 	str msg = MAL_SUCCEED;
 	int res;
 
@@ -94,20 +92,17 @@ OPTstrimpsImplementation(Client cntxt, M
 			freeInstruction(old[i]);
 	GDKfree(old);
 
-    /* Defense line against incorrect plans */
-    if (actions){
-        msg = chkTypes(cntxt->usermodule, mb, FALSE);
-	if (!msg)
-        	msg = chkFlow(mb);
-	if (!msg)
-        	msg = chkDeclarations(mb);
-    }
-    /* keep all actions taken as a post block comment */
+	/* Defense line against incorrect plans */
+	if (actions){
+		msg = chkTypes(cntxt->usermodule, mb, FALSE);
+		if (!msg)
+			msg = chkFlow(mb);
+		if (!msg)
+			msg = chkDeclarations(mb);
+	}
+	/* keep all actions taken as a post block comment */
 bailout:
-	usec = GDKusec()- usec;
-	snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","strimps",actions,usec);
-	newComment(mb,buf);
-	if( actions > 0)
-		addtoMalBlkHistory(mb);
+	/* keep actions taken as a fake argument*/
+	(void) pushInt(mb, pci, actions);
 	return msg;
 }
--- a/sql/backends/monet5/generator/generator.c
+++ b/sql/backends/monet5/generator/generator.c
@@ -700,12 +700,12 @@ str VLTgenerator_thetasubselect(Client c
 
 	if( cndid)
 		BBPunfix(cndid);
+	BATsetcount(bn,c);
 	bn->tsorted = true;
 	bn->trevsorted = false;
 	bn->tkey = true;
 	bn->tnil = false;
 	bn->tnonil = true;
-	BATsetcount(bn,c);
 	BBPkeepref(*getArgReference_bat(stk,pci,0)= bn->batCacheid);
 	return MAL_SUCCEED;
 }
@@ -843,11 +843,11 @@ str VLTgenerator_projection(Client cntxt
 	/* adminstrative wrapup of the projection */
 	BBPunfix(b->batCacheid);
 	if( bn){
+		BATsetcount(bn,c);
 		bn->tsorted = bn->trevsorted = false;
 		bn->tkey = false;
 		bn->tnil = false;
 		bn->tnonil = false;
-		BATsetcount(bn,c);
 		BBPkeepref(*getArgReference_bat(stk,pci,0)= bn->batCacheid);
 	}
 	return MAL_SUCCEED;
@@ -984,19 +984,19 @@ str VLTgenerator_join(Client cntxt, MalB
 		throw(MAL,"generator.join", SQLSTATE(42000) "Illegal type");
 	}
 
+	BATsetcount(bln,c);
 	bln->tsorted = bln->trevsorted = false;
 	bln->tkey = false;
 	bln->tnil = false;
 	bln->tnonil = false;
-	BATsetcount(bln,c);
 	bln->tsorted = incr || c <= 1;
 	bln->trevsorted = !incr || c <= 1;
 
+	BATsetcount(brn,c);
 	brn->tsorted = brn->trevsorted = false;
 	brn->tkey = false;
 	brn->tnil = false;
 	brn->tnonil = false;
-	BATsetcount(brn,c);
 	brn->tsorted = incr || c <= 1;
 	brn->trevsorted = !incr || c <= 1;
 	if( q){
@@ -1139,19 +1139,19 @@ str VLTgenerator_rangejoin(Client cntxt,
 		throw(MAL,"generator.rangejoin","Illegal type");
 	}
 
+	BATsetcount(bln,c);
 	bln->tsorted = bln->trevsorted = false;
 	bln->tkey = false;
 	bln->tnil = false;
 	bln->tnonil = false;
-	BATsetcount(bln,c);
 	bln->tsorted = incr || c <= 1;
 	bln->trevsorted = !incr || c <= 1;
 
+	BATsetcount(brn,c);
 	brn->tsorted = brn->trevsorted = false;
 	brn->tkey = false;
 	brn->tnil = false;
 	brn->tnonil = false;
-	BATsetcount(brn,c);
 	brn->tsorted = incr || c <= 1;
 	brn->trevsorted = !incr || c <= 1;
 	BBPkeepref(*getArgReference_bat(stk,pci,0)= bln->batCacheid);
--- a/sql/backends/monet5/sql.c
+++ b/sql/backends/monet5/sql.c
@@ -1064,9 +1064,9 @@ mvc_restart_seq(Client cntxt, MalBlkPtr 
 		throw(SQL, "sql.restart", SQLSTATE(HY050) "Failed to fetch sequence %s.%s", sname, seqname);
 	if (is_lng_nil(start))
 		throw(SQL, "sql.restart", SQLSTATE(HY050) "Cannot (re)start sequence %s.%s with NULL", sname, seqname);
-	if (seq->minvalue && start < seq->minvalue)
+	if (start < seq->minvalue)
 		throw(SQL, "sql.restart", SQLSTATE(HY050) "Cannot set sequence %s.%s start to a value lesser than the minimum ("LLFMT" < "LLFMT")", sname, seqname, start, seq->minvalue);
-	if (seq->maxvalue && start > seq->maxvalue)
+	if (start > seq->maxvalue)
 		throw(SQL, "sql.restart", SQLSTATE(HY050) "Cannot set sequence %s.%s start to a value higher than the maximum ("LLFMT" > "LLFMT")", sname, seqname, start, seq->maxvalue);
 	switch (sql_trans_sequence_restart(m->session->tr, seq, start)) {
 		case -1:
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -793,12 +793,19 @@ create_seq(mvc *sql, char *sname, char *
 	if (is_lng_nil(seq->start) || is_lng_nil(seq->minvalue) || is_lng_nil(seq->maxvalue) ||
 			   is_lng_nil(seq->increment) || is_lng_nil(seq->cacheinc) || is_bit_nil(seq->cycle))
 		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: sequence properties must be non-NULL");
-	if (seq->minvalue && seq->start < seq->minvalue)
+	if (seq->start < seq->minvalue)
 		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: start value is lesser than the minimum ("LLFMT" < "LLFMT")", seq->start, seq->minvalue);
-	if (seq->maxvalue && seq->start > seq->maxvalue)
+	if (seq->start > seq->maxvalue)
 		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: start value is higher than the maximum ("LLFMT" > "LLFMT")", seq->start, seq->maxvalue);
-	if (seq->minvalue && seq->maxvalue && seq->maxvalue < seq->minvalue)
+	if (seq->maxvalue < seq->minvalue)
 		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: maximum value is lesser than the minimum ("LLFMT" < "LLFMT")", seq->maxvalue, seq->minvalue);
+	if (seq->increment == 0)
+		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: sequence increment cannot be 0");
+	if (seq->cacheinc <= 0)
+		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: sequence cache must be positive");
+	lng calc = llabs(seq->increment) * seq->cacheinc;
+	if (calc < llabs(seq->increment) || calc < seq->cacheinc)
+		throw(SQL,"sql.create_seq", SQLSTATE(42000) "CREATE SEQUENCE: The specified range of cached values cannot be set. Either reduce increment or cache value");
 	switch (sql_trans_create_sequence(sql->session->tr, s, seq->base.name, seq->start, seq->minvalue, seq->maxvalue, seq->increment, seq->cacheinc, seq->cycle, seq->bedropped)) {
 		case -1:
 			throw(SQL,"sql.create_seq",SQLSTATE(HY013) MAL_MALLOC_FAIL);
@@ -835,14 +842,21 @@ alter_seq(mvc *sql, char *sname, char *s
 		default:
 			break;
 	}
-	if (nseq->minvalue && nseq->maxvalue && nseq->maxvalue < seq->minvalue)
-		throw(SQL, "sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: maximum value is lesser than the minimum ("LLFMT" < "LLFMT")", nseq->maxvalue, nseq->minvalue);
+	if (nseq->maxvalue < nseq->minvalue)
+		throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: maximum value is lesser than the minimum ("LLFMT" < "LLFMT")", nseq->maxvalue, nseq->minvalue);
+	if (nseq->increment == 0)
+		throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: sequence increment cannot be 0");
+	if (nseq->cacheinc <= 0)
+		throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: sequence cache must be positive");
+	lng calc = llabs(nseq->increment) * nseq->cacheinc;
+	if (calc < llabs(nseq->increment) || calc < nseq->cacheinc)
+		throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: The specified range of cached values cannot be set. Either reduce increment or cache value");
 	if (val) {
 		if (is_lng_nil(*val))
 			throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: sequence value must be non-NULL");
-		if (nseq->minvalue && *val < nseq->minvalue)
+		if (*val < nseq->minvalue)
 			throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: cannot set sequence start to a value lesser than the minimum ("LLFMT" < "LLFMT")", *val, nseq->minvalue);
-		if (nseq->maxvalue && *val > nseq->maxvalue)
+		if (*val > nseq->maxvalue)
 			throw(SQL,"sql.alter_seq", SQLSTATE(42000) "ALTER SEQUENCE: cannot set sequence start to a value higher than the maximum ("LLFMT" > "LLFMT")", *val, nseq->maxvalue);
 		switch (sql_trans_sequence_restart(sql->session->tr, nseq, *val)) {
 			case -1:
--- a/sql/backends/monet5/sql_gencode.c
+++ b/sql/backends/monet5/sql_gencode.c
@@ -1107,7 +1107,7 @@ backend_create_mal_func(mvc *m, sql_func
 {
 	if (f->instantiated)
 		return 0;
-	lock_function(m->store, f->base.id);
+	MT_lock_set(&f->function_lock);
 	if (!f->instantiated) {
 		char *F = NULL, *fn = NULL;
 		bit side_effect = f->side_effect;
@@ -1117,29 +1117,29 @@ backend_create_mal_func(mvc *m, sql_func
 		(void) F;
 		if (strlen(f->mod) >= IDLENGTH) {
 			(void) sql_error(m, 01, SQLSTATE(42000) "MAL module name '%s' too large for the backend", f->mod);
-			unlock_function(m->store, f->base.id);
+			MT_lock_unset(&f->function_lock);
 			return -1;
 		}
 		if (mal_function_find_implementation_address(m, f) < 0) {
-			unlock_function(m->store, f->base.id);
+			MT_lock_unset(&f->function_lock);
 			return -1;
 		}
 		if (!backend_resolve_function(&clientid, f)) {
 			(void) sql_error(m, 02, SQLSTATE(3F000) "MAL external name %s.%s not bound (%s.%s)", f->mod, f->imp, f->s->base.name, f->base.name);
 			_DELETE(f->imp);
-			unlock_function(m->store, f->base.id);
+			MT_lock_unset(&f->function_lock);
 			return -1;
 		}
 		if (side_effect != f->side_effect) {
 			(void) sql_error(m, 02, SQLSTATE(42000) "Side-effect value from the SQL %s %s.%s doesn't match the MAL definition %s.%s\n"
 							 "Either re-create the %s, or fix the MAL definition and restart the database", fn, f->s->base.name, f->base.name, f->mod, f->imp, fn);
 			_DELETE(f->imp);
-			unlock_function(m->store, f->base.id);
+			MT_lock_unset(&f->function_lock);
 			return -1;
 		}
 		f->instantiated = TRUE; /* make sure 'instantiated' gets set after 'imp' */
 	}
-	unlock_function(m->store, f->base.id);
+	MT_lock_unset(&f->function_lock);
 	return 0;
 }
 
@@ -1153,7 +1153,7 @@ backend_create_sql_func(backend *be, sql
 	if (f->instantiated || (m->forward && m->forward->base.id == f->base.id))
 		return res;
 
-	lock_function(m->store, f->base.id);
+	MT_lock_set(&f->function_lock);
 	if (!f->instantiated) {
 		MalBlkPtr curBlk = NULL;
 		InstrPtr curInstr = NULL;
@@ -1171,7 +1171,7 @@ backend_create_sql_func(backend *be, sql
 		if (r)
 			r = sql_processrelation(m, r, 1, 1, 0);
 		if (!r) {
-			unlock_function(m->store, f->base.id);
+			MT_lock_unset(&f->function_lock);
 			return -1;
 		}
 
@@ -1179,7 +1179,7 @@ backend_create_sql_func(backend *be, sql
 		/* for debug builds we keep the SQL function name in the MAL function name to make it easy to debug */
 		if (strlen(f->base.name) + 21 >= IDLENGTH) { /* 20 bits for u64 number + '%' */
 			(void) sql_error(m, 01, SQLSTATE(42000) "MAL function name '%s' too large for the backend", f->base.name);
-			unlock_function(m->store, f->base.id);
+			MT_lock_unset(&f->function_lock);
 			return -1;
 		}
 		(void) snprintf(befname, IDLENGTH, "%%" LLFMT "%s", store_function_counter(m->store), f->base.name);
@@ -1334,7 +1334,7 @@ cleanup:
 		memcpy(be, &bebackup, sizeof(backend));
 		c->curprg = symbackup;
 	}
-	unlock_function(m->store, f->base.id);
+	MT_lock_unset(&f->function_lock);
 	return res;
 }
 
--- a/sql/backends/monet5/sql_result.c
+++ b/sql/backends/monet5/sql_result.c
@@ -1802,7 +1802,7 @@ mvc_export_table(backend *b, stream *s, 
 int
 mvc_export(mvc *m, stream *s, res_table *t, BUN nr)
 {
-	backend b;
+	backend b = {0};
 	b.mvc = m;
 	b.results = t;
 	b.reloptimizer = 0;
@@ -2089,7 +2089,7 @@ mvc_export_head(backend *b, stream *s, i
 
 	/* row count, min(count, reply_size) */
 	/* the columnar protocol ignores the reply size by fetching the entire resultset at once, so don't set it */
-	if (mvc_send_int(s, (b->client->protocol != PROTOCOL_COLUMNAR && m->reply_size >= 0 && (BUN) m->reply_size < count) ? m->reply_size : (int) count) != 1)
+	if (mvc_send_int(s, (b->client && b->client->protocol != PROTOCOL_COLUMNAR && m->reply_size >= 0 && (BUN) m->reply_size < count) ? m->reply_size : (int) count) != 1)
 		return -4;
 
 	// export query id
--- a/sql/backends/monet5/sql_scenario.c
+++ b/sql/backends/monet5/sql_scenario.c
@@ -484,8 +484,8 @@ SQLinit(Client c)
 		 * server after an incomplete initialization */
 		if ((msg = SQLtrans(m)) == MAL_SUCCEED) {
 			/* TODO there's a going issue with loading triggers due to system tables,
-			   so at the moment check for existence of 'logging' schema from 81_tracer.sql */
-			if (!mvc_bind_schema(m, "logging"))
+			   so at the moment check for existence of 'json' schema from 40_json.sql */
+			if (!mvc_bind_schema(m, "json"))
 				store->first = 1;
 			msg = mvc_rollback(m, 0, NULL, false);
 		}
--- a/sql/backends/monet5/sql_strimps.c
+++ b/sql/backends/monet5/sql_strimps.c
@@ -27,14 +27,24 @@ sql_load_bat(Client cntxt, MalBlkPtr mb,
 	tbl = *getArgReference_str(stk, pci, 2);
 	col = *getArgReference_str(stk, pci, 3);
 
+	if (strNil(sch))
+		throw(SQL, "sql.createstrimps", SQLSTATE(42000) "Schema name cannot be NULL");
+	if (strNil(tbl))
+		throw(SQL, "sql.createstrimps", SQLSTATE(42000) "Table name cannot be NULL");
+	if (strNil(col))
+		throw(SQL, "sql.createstrimps", SQLSTATE(42000) "Column name cannot be NULL");
+
 	if (!(s = mvc_bind_schema(m, sch)))
 		throw(SQL, "sql.createstrimps", SQLSTATE(3FOOO) "Unknown schema %s", sch);
 
 	if (!mvc_schema_privs(m, s))
 		throw(SQL, "sql.createstrimps", SQLSTATE(42000) "Access denied for %s to schema '%s'",
 			  get_string_global_var(m, "current_user"), s->base.name);
-	if (!(t = mvc_bind_table(m, s, tbl)) || !isTable(t))
+	if (!(t = mvc_bind_table(m, s, tbl)))
 		throw(SQL, "sql.createstrimps", SQLSTATE(42S02) "Unknown table %s.%s", sch, tbl);
+	if (!isTable(t))
+		throw(SQL, "sql.createstrimps", SQLSTATE(42000) "%s '%s' is not persistent",
+			  TABLE_TYPE_DESCRIPTION(t->type, t->properties), t->base.name);
 	if (!(c = mvc_bind_column(m, t, col)))
 		throw(SQL, "sql.createstrimps", SQLSTATE(38000) "Unknown column %s.%s.%s", sch, tbl, col);
 
@@ -51,16 +61,23 @@ str
 sql_createstrimps(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
 {
 	BAT *b, *s;
+	gdk_return res;
+	str msg = MAL_SUCCEED;
 
-	if (sql_load_bat(cntxt, mb, stk, pci, &b) != MAL_SUCCEED)
-		throw(SQL, "sql.createstrimps", SQLSTATE(HY002) OPERATION_FAILED);
+	if ((msg = sql_load_bat(cntxt, mb, stk, pci, &b)) != MAL_SUCCEED)
+		return msg;
 
-	s = BATdense(0, 0, b->batCount);
+	if (!(s = BATdense(0, 0, b->batCount))) {
+		BBPunfix(b->batCacheid);
+		throw(SQL, "sql.createstrimps", SQLSTATE(HY013) MAL_MALLOC_FAIL);
+	}
 
-	if (STRMPcreate(b, s) != GDK_SUCCEED)
-		throw(SQL, "sql.createstrimps", SQLSTATE(HY002) OPERATION_FAILED);
+	res = STRMPcreate(b, s);
+	BBPunfix(b->batCacheid);
+	BBPunfix(s->batCacheid);
+	if (res != GDK_SUCCEED)
+		throw(SQL, "sql.createstrimps", GDK_EXCEPTION);
 
-	BBPunfix(b->batCacheid);
 	return MAL_SUCCEED;
 }
 
--- a/sql/backends/monet5/sql_upgrades.c
+++ b/sql/backends/monet5/sql_upgrades.c
@@ -2774,7 +2774,7 @@ sql_update_jul2021(Client c, mvc *sql, c
 					"        s.name as sch,\n"
 					"        seq.name as seq,\n"
 					"        seq.\"start\" s,\n"
-					"        get_value_for(s.name, seq.name) AS rs,\n"
+					"        sys.peak_next_value_for(s.name, seq.name) AS rs,\n"
 					"        seq.\"minvalue\" mi,\n"
 					"        seq.\"maxvalue\" ma,\n"
 					"        seq.\"increment\" inc,\n"
--- a/sql/include/sql_catalog.h
+++ b/sql/include/sql_catalog.h
@@ -516,6 +516,7 @@ typedef struct sql_func {
 	 		*/
 	sql_schema *s;
 	sql_allocator *sa;
+	MT_Lock function_lock; /* protecting concurrent function instantiations. Only used in MAL and SQL functions */
 } sql_func;
 
 typedef struct sql_subfunc {
--- a/sql/scripts/52_describe.sql
+++ b/sql/scripts/52_describe.sql
@@ -491,7 +491,7 @@ CREATE VIEW sys.describe_sequences AS
 		s.name as sch,
 		seq.name as seq,
 		seq."start" s,
-		get_value_for(s.name, seq.name) AS rs,
+		peak_next_value_for(s.name, seq.name) AS rs,
 		seq."minvalue" mi,
 		seq."maxvalue" ma,
 		seq."increment" inc,
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -3547,13 +3547,18 @@ merge_notequal(mvc *sql, list *exps, int
 		for (node *n = inequality_groups->h; n; n = n->next) {
 			list *next = n->data;
 			sql_exp *first = (sql_exp*) next->h->data;
-			list *notin = new_exp_list(sql->sa);
-
-			for (node *m = next->h; m; m = m->next) {
-				sql_exp *e = m->data;
-				list_append(notin, e->r);
-			}
-			list_append(nexps, exp_in(sql->sa, first->l, notin, cmp_notin));
+
+			if (list_length(next) > 1) {
+				list *notin = new_exp_list(sql->sa);
+
+				for (node *m = next->h; m; m = m->next) {
+					sql_exp *e = m->data;
+					list_append(notin, e->r);
+				}
+				list_append(nexps, exp_in(sql->sa, first->l, notin, cmp_notin));
+			} else {
+				list_append(nexps, first);
+			}
 		}
 
 		for (node *n = exps->h; n; n = n->next) {
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -89,23 +89,51 @@ rel_destroy_(sql_rel *rel)
 {
 	if (!rel)
 		return;
-	if (is_join(rel->op) ||
-	    is_semi(rel->op) ||
-	    is_select(rel->op) ||
-	    is_set(rel->op) ||
-	    is_topn(rel->op) ||
-		is_sample(rel->op) ||
-		is_merge(rel->op)) {
+	switch(rel->op){
+	case op_basetable:
+		break;
+	case op_table:
+		if ((IS_TABLE_PROD_FUNC(rel->flag) || rel->flag == TABLE_FROM_RELATION) && rel->l)
+			rel_destroy(rel->l);
+		break;
+	case op_join:
+	case op_left:
+	case op_right:
+	case op_full:
+	case op_semi:
+	case op_anti:
+	case op_union:
+	case op_inter:
+	case op_except:
+	case op_insert:
+	case op_update:
+	case op_delete:
+	case op_merge:
 		if (rel->l)
 			rel_destroy(rel->l);
 		if (rel->r)
 			rel_destroy(rel->r);
-	} else if (is_simple_project(rel->op) || is_groupby(rel->op)) {
+		break;
+	case op_project:
+	case op_groupby:
+	case op_select:
+	case op_topn:
+	case op_sample:
+	case op_truncate:
 		if (rel->l)
 			rel_destroy(rel->l);
-	} else if (is_insert(rel->op) || is_update(rel->op) || is_delete(rel->op) || is_truncate(rel->op)) {
-		if (rel->r)
-			rel_destroy(rel->r);
+		break;
+	case op_ddl:
+		if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view) {
+			if (rel->l)
+				rel_destroy(rel->l);
+		} else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
+			if (rel->l)
+				rel_destroy(rel->l);
+			if (rel->r)
+				rel_destroy(rel->r);
+		}
+		break;
 	}
 }
 
@@ -151,7 +179,8 @@ rel_copy(mvc *sql, sql_rel *i, int deep)
 		rel_base_copy(sql, i, rel);
 		break;
 	case op_table:
-		rel->l = i->l;
+		if ((IS_TABLE_PROD_FUNC(i->flag) || i->flag == TABLE_FROM_RELATION) && i->l)
+			rel->l = rel_copy(sql, i->l, deep);
 		rel->r = i->r;
 		break;
 	case op_project:
@@ -167,7 +196,7 @@ rel_copy(mvc *sql, sql_rel *i, int deep)
 		}
 		break;
 	case op_ddl:
-		if (rel->flag == ddl_output || rel->flag == ddl_create_seq || rel->flag == ddl_alter_seq || rel->flag == ddl_alter_table || rel->flag == ddl_create_table || rel->flag == ddl_create_view) {
+		if (i->flag == ddl_output || i->flag == ddl_create_seq || i->flag == ddl_alter_seq || i->flag == ddl_alter_table || i->flag == ddl_create_table || i->flag == ddl_create_view) {
 			if (i->l)
 				rel->l = rel_copy(sql, i->l, deep);
 		} else if (rel->flag == ddl_list || rel->flag == ddl_exception) {
@@ -184,10 +213,6 @@ rel_copy(mvc *sql, sql_rel *i, int deep)
 		if (i->l)
 			rel->l = rel_copy(sql, i->l, deep);
 		break;
-	case op_insert:
-	case op_update:
-	case op_delete:
-
 	case op_join:
 	case op_left:
 	case op_right:
@@ -198,6 +223,10 @@ rel_copy(mvc *sql, sql_rel *i, int deep)
 	case op_union:
 	case op_inter:
 	case op_except:
+
+	case op_insert:
+	case op_update:
+	case op_delete:
 	case op_merge:
 		if (i->l)
 			rel->l = rel_copy(sql, i->l, deep);
--- a/sql/server/rel_sequence.c
+++ b/sql/server/rel_sequence.c
@@ -77,12 +77,16 @@ rel_create_seq(
 	sql_subtype *tpe,
 	lng start,
 	lng inc,
-	lng min,
-	lng max,
+	symbol* s_min,
+	symbol* s_max,
 	lng cache,
 	bit cycle,
 	bit bedropped)
 {
+	bit nomin = s_min && s_min ->type == type_int ? 1: 0;
+	bit nomax = s_max && s_max ->type == type_int ? 1: 0;
+	lng min = s_min ? s_min->data.l_val : lng_nil;
+	lng max = s_max ? s_max->data.l_val : lng_nil;
 	sql_rel *res = NULL;
 	sql_sequence *seq = NULL;
 	char *sname = qname_schema(qname);
@@ -102,12 +106,27 @@ rel_create_seq(
 
 	/* generate defaults */
 	if (is_lng_nil(inc)) inc = 1;
+	if (nomin) min = GDK_lng_min;
+	if (nomax) max = GDK_lng_max;
 	if (is_lng_nil(min)) min = inc > 0 ? 0 : GDK_lng_min;
 	if (is_lng_nil(max)) max = inc > 0 ? GDK_lng_max : 0;
-	if (is_lng_nil(start)) start = inc > 0 ? 1 : -1;
+	if (is_lng_nil(start)) {if (inc > 0) start = nomin ? 1 : min ? min : 1; else if (inc < 0) start = nomax ? -1 : max ? max : -1;}
 	if (is_lng_nil(cache)) cache = 1;
+	if (is_bit_nil(cycle)) cycle = 0;
 
-	// TODO: check that min < max and min <= start <= max and inc != 0 and inc * cache > 0 does not overflow?
+	if (inc == 0)
+		return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: INCREMENT cannot be 0");
+	if (cache <= 0)
+		return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: CACHE must be positive");
+	lng calc = llabs(inc) * cache;
+	if (calc < llabs(inc) || calc < cache)
+		return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: The specified range of cached values cannot be set. Either reduce increment or cache value");
+	if (max < min)
+		return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: MAXVALUE value is lesser than MINVALUE ("LLFMT" < "LLFMT")", max, min);
+	if (start < min)
+		return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: START value is lesser than MINVALUE ("LLFMT" < "LLFMT")", start, min);
+	if (start > max)
+		return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: START value is higher than MAXVALUE ("LLFMT" > "LLFMT")", start, max);
 
 	seq = create_sql_sequence(sql->store, sql->sa, s, name, start, min, max, inc, cache, cycle);
 	seq->bedropped = bedropped;
@@ -138,7 +157,8 @@ list_create_seq(
 {
 	dnode *n;
 	sql_subtype *t = NULL;
-	lng start = lng_nil, inc = lng_nil, min = lng_nil, max = lng_nil, cache = lng_nil;
+	lng start = lng_nil, inc = lng_nil, cache = lng_nil;
+	symbol* min = NULL,* max = NULL;
 	unsigned int used = 0;
 	bit cycle = 0;
 
@@ -186,17 +206,25 @@ list_create_seq(
 				if ((used&(1<<SEQ_MIN)))
 					return sql_error(sql, 02, SQLSTATE(3F000) "CREATE SEQUENCE: MINVALUE or NO MINVALUE should be passed as most once");
 				used |= (1<<SEQ_MIN);
-				if (is_lng_nil(s->data.l_val))
-					return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: MINVALUE must not be null");
-				min = s->data.l_val;
+				if (s->type == type_lng) {
+					 if (is_lng_nil(s->data.l_val))
+					 	return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: MINVALUE must not be null");
+				}
+				assert(s->type == type_lng || (s->type == type_int && is_int_nil(s->data.i_val)));
+				// int_nil signals NO MINVALUE
+				min = s;
 				break;
 			case SQL_MAXVALUE:
 				if ((used&(1<<SEQ_MAX)))
 					return sql_error(sql, 02, SQLSTATE(3F000) "CREATE SEQUENCE: MAXVALUE or NO MAXVALUE should be passed as most once");
 				used |= (1<<SEQ_MAX);
-				if (is_lng_nil(s->data.l_val))
-					return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: MAXVALUE must be non-NULL");
-				max = s->data.l_val;
+				if (s->type == type_lng) {
+					 if (is_lng_nil(s->data.l_val))
+					 	return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: MAXVALUE must not be null");
+				}
+				assert(s->type == type_lng || (s->type == type_int && is_int_nil(s->data.i_val)));
+				// int_nil signals NO MAXVALUE
+				max = s;
 				break;
 			case SQL_CYCLE:
 				if ((used&(1<<SEQ_CYCLE)))
@@ -216,17 +244,7 @@ list_create_seq(
 				assert(0);
 			}
 		}
-		if (!is_lng_nil(start)) {
-			if (!is_lng_nil(min) && start < min)
-				return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: START value is lesser than MINVALUE ("LLFMT" < "LLFMT")", start, min);
-			if (!is_lng_nil(max) && start > max)
-				return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: START value is higher than MAXVALUE ("LLFMT" > "LLFMT")", start, max);
-		}
-		if (!is_lng_nil(min) && !is_lng_nil(max) && max < min)
-			return sql_error(sql, 02, SQLSTATE(42000) "CREATE SEQUENCE: MAXVALUE value is lesser than MINVALUE ("LLFMT" < "LLFMT")", max, min);
 	}
-	if (is_lng_nil(start) && !is_lng_nil(min) && min) /* if start value not set, set it to the minimum if available */
-		start = min;
 	return rel_create_seq(sql, qname, t, start, inc, min, max, cache, cycle, bedropped);
 }
 
@@ -237,11 +255,15 @@ rel_alter_seq(
 		sql_subtype *tpe,
 		dlist* start_list,
 		lng inc,
-		lng min,
-		lng max,
+		symbol* s_min,
+		symbol* s_max,
 		lng cache,
 		bit cycle)
 {
+	bit nomin = s_min && s_min ->type == type_int ? 1: 0;
+	bit nomax = s_max && s_max ->type == type_int ? 1: 0;
+	lng min = s_min ? s_min->data.l_val : lng_nil;
+	lng max = s_max ? s_max->data.l_val : lng_nil;
 	mvc *sql = query->sql;
 	char *sname = qname_schema(qname);
 	char *name = qname_schema_object(qname);
@@ -258,8 +280,26 @@ rel_alter_seq(
 		return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: insufficient privileges "
 				"for '%s' in schema '%s'", get_string_global_var(sql, "current_user"), seq->s->base.name);
 
+	/* if not being modified, use existing values */
+	if (is_lng_nil(inc)) inc = seq->increment;
+	if (nomin) min = GDK_lng_min;
+	if (nomax) max = GDK_lng_max;
+	if (is_lng_nil(min)) min = seq->minvalue;
+	if (is_lng_nil(max)) max = seq->maxvalue;
+	if (is_lng_nil(cache)) cache = seq->cacheinc;
+	if (is_bit_nil(cycle)) cycle = seq->cycle;
+
+	if (inc == 0)
+		return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: INCREMENT cannot be 0");
+	if (cache <= 0)
+		return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: CACHE must be positive");
+	lng calc = llabs(inc) * cache;
+	if (calc < llabs(inc) || calc < cache)
+		return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: The specified range of cached values cannot be set. Either reduce increment or cache value");
+	if (max < min)
+		return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: MAXVALUE value is lesser than MINVALUE ("LLFMT" < "LLFMT")", max, min);
 	/* first alter the known values */
-	seq = create_sql_sequence(sql->store, sql->sa, seq->s, name, seq->start, min, max, inc, cache, (bit) cycle);
+	seq = create_sql_sequence(sql->store, sql->sa, seq->s, name, seq->start, min, max, inc, cache, cycle);
 
 	/* restart may be a query, i.e. we create a statement
 	   restart(ssname,seqname,value) */
@@ -297,7 +337,8 @@ list_alter_seq(
 	mvc *sql = query->sql;
 	dnode *n;
 	sql_subtype* t = NULL;
-	lng inc = lng_nil, min = lng_nil, max = lng_nil, cache = lng_nil;
+	lng inc = lng_nil, cache = lng_nil;
+	symbol* min = NULL,* max = NULL;
 	dlist *start = NULL;
 	unsigned int used = 0;
 	bit cycle = 0;
@@ -333,17 +374,25 @@ list_alter_seq(
 			if ((used&(1<<SEQ_MIN)))
 				return sql_error(sql, 02, SQLSTATE(3F000) "ALTER SEQUENCE: MINVALUE or NO MINVALUE should be passed as most once");
 			used |= (1<<SEQ_MIN);
-			if (is_lng_nil(s->data.l_val))
-				return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: MINVALUE must be non-NULL");
-			min = s->data.l_val;
+			if (s->type == type_lng) {
+				if (is_lng_nil(s->data.l_val))
+					return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: MINVALUE must not be null");
+			}
+			assert(s->type == type_lng || (s->type == type_int && is_int_nil(s->data.i_val)));
+			min = s;
+			// int_nil signals NO MINVALUE
 			break;
 		case SQL_MAXVALUE:
 			if ((used&(1<<SEQ_MAX)))
 				return sql_error(sql, 02, SQLSTATE(3F000) "ALTER SEQUENCE: MAXVALUE or NO MAXVALUE should be passed as most once");
 			used |= (1<<SEQ_MAX);
-			if (is_lng_nil(s->data.l_val))
-				return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: MAXVALUE must be non-NULL");
-			max = s->data.l_val;
+			if (s->type == type_lng) {
+				if (is_lng_nil(s->data.l_val))
+					return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: MAXVALUE must not be null");
+			}
+			assert(s->type == type_lng || (s->type == type_int && is_int_nil(s->data.i_val)));
+			// int_nil signals NO MAXVALUE
+			max = s;
 			break;
 		case SQL_CYCLE:
 			if ((used&(1<<SEQ_CYCLE)))
@@ -363,8 +412,6 @@ list_alter_seq(
 			assert(0);
 		}
 	}
-	if (!is_lng_nil(min) && !is_lng_nil(max) && max < min)
-		return sql_error(sql, 02, SQLSTATE(42000) "ALTER SEQUENCE: MAXVALUE value is lesser than MINVALUE ("LLFMT" < "LLFMT")", max, min);
 	return rel_alter_seq(query, qname, t, start, inc, min, max, cache, cycle);
 }
 
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -1425,9 +1425,9 @@ opt_alt_seq_param:
 opt_seq_common_param:
 	INCREMENT BY opt_sign lngval	{ $$ = _symbol_create_lng(SQL_INC, is_lng_nil($4) ? $4 : $3 * $4); }
   |	MINVALUE opt_sign lngval	{ $$ = _symbol_create_lng(SQL_MINVALUE, is_lng_nil($3) ? $3 : $2 * $3); }
-  |	NO MINVALUE			{ $$ = _symbol_create_lng(SQL_MINVALUE, 0); }
+  |	NO MINVALUE			{ $$ = _symbol_create_int(SQL_MINVALUE, int_nil); /* Hack: SQL_MINVALUE + int_nil signals NO MINVALUE */ }
   |	MAXVALUE opt_sign lngval	{ $$ = _symbol_create_lng(SQL_MAXVALUE, is_lng_nil($3) ? $3 : $2 * $3); }
-  |	NO MAXVALUE			{ $$ = _symbol_create_lng(SQL_MAXVALUE, 0); }
+  |	NO MAXVALUE			{ $$ = _symbol_create_int(SQL_MAXVALUE, int_nil); /* Hack: SQL_MAXVALUE + int_nil signals NO MAXVALUE */ }
   |	CACHE nonzerolng		{ $$ = _symbol_create_lng(SQL_CACHE, $2); }
   |	CYCLE				{ $$ = _symbol_create_int(SQL_CYCLE, 1); }
   |	NO CYCLE			{ $$ = _symbol_create_int(SQL_CYCLE, 0); }
--- a/sql/server/sql_qc.c
+++ b/sql/server/sql_qc.c
@@ -154,6 +154,7 @@ qc_insert(qc *cache, sql_allocator *sa, 
 	*f = (sql_func) {
 		.mod = sql_private_module_name,
 		.type = F_PROC,
+		.lang = FUNC_LANG_INT,
 		.query = cmd,
 		.ops = params,
 		.res = res,
--- a/sql/storage/sql_storage.h
+++ b/sql/storage/sql_storage.h
@@ -335,8 +335,6 @@ extern lng store_hot_snapshot(struct sql
 extern lng store_hot_snapshot_to_stream(struct sqlstore *store, stream *s);
 
 extern ulng store_function_counter(struct sqlstore *store);
-extern void lock_function(struct sqlstore *store, sqlid id);
-extern void unlock_function(struct sqlstore *store, sqlid id);
 
 extern ulng store_oldest(struct sqlstore *store);
 extern ulng store_get_timestamp(struct sqlstore *store);
@@ -461,7 +459,6 @@ extern int sql_trans_copy_key(sql_trans 
 extern int sql_trans_copy_idx(sql_trans *tr, sql_table *t, sql_idx *i, sql_idx **ires);
 extern int sql_trans_copy_trigger(sql_trans *tr, sql_table *t, sql_trigger *tri, sql_trigger **tres);
 
-#define NR_FUNCTION_LOCKS 16
 #define NR_TABLE_LOCKS 64
 #define NR_COLUMN_LOCKS 512
 #define TRANSACTION_ID_BASE	(1ULL<<63)
@@ -473,7 +470,6 @@ typedef struct sqlstore {
 	MT_Lock lock;			/* lock protecting concurrent writes (not reads, ie use rcu) */
 	MT_Lock commit;			/* protect transactions, only single commit (one wal writer) */
 	MT_Lock flush;			/* flush lock protecting concurrent writes (not reads, ie use rcu) */
-	MT_Lock function_locks[NR_FUNCTION_LOCKS];		/* protecting concurrent function instantiations */
 	MT_Lock table_locks[NR_TABLE_LOCKS];		/* protecting concurrent writes to tables (storage) */
 	MT_Lock column_locks[NR_COLUMN_LOCKS];		/* protecting concurrent writes to columns (storage) */
 	list *active;			/* list of running transactions */
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -30,18 +30,6 @@ store_function_counter(sqlstore *store)
 	return ts;
 }
 
-void
-lock_function(sqlstore *store, sqlid id)
-{
-	MT_lock_set(&store->function_locks[id&(NR_FUNCTION_LOCKS-1)]);
-}
-
-void
-unlock_function(sqlstore *store, sqlid id)
-{
-	MT_lock_unset(&store->function_locks[id&(NR_FUNCTION_LOCKS-1)]);
-}
-
 static ulng
 store_timestamp(sqlstore *store)
 {
@@ -128,6 +116,8 @@ func_destroy(sqlstore *store, sql_func *
 		/* clean backend code */
 		backend_freecode(sql_shared_module_name, 0, f->imp);
 	}
+	if (f->lang == FUNC_LANG_SQL || f->lang == FUNC_LANG_MAL)
+		MT_lock_destroy(&f->function_lock);
 	if (f->res)
 		list_destroy2(f->res, store);
 	list_destroy2(f->ops, store);
@@ -948,6 +938,8 @@ load_func(sql_trans *tr, sql_schema *s, 
 	t->s = s;
 	t->fix_scale = SCALE_EQ;
 	t->sa = tr->sa;
+	if (!t->instantiated)
+		MT_lock_init(&t->function_lock, "function_lock");
 	if (t->lang != FUNC_LANG_INT) {
 		t->query = t->imp;
 		t->imp = NULL;
@@ -2102,8 +2094,6 @@ store_init(int debug, store_type store_t
 	MT_lock_init(&store->lock, "sqlstore_lock");
 	MT_lock_init(&store->commit, "sqlstore_commit");
 	MT_lock_init(&store->flush, "sqlstore_flush");
-	for(int i = 0; i<NR_FUNCTION_LOCKS; i++)
-		MT_lock_init(&store->function_locks[i], "sqlstore_function");
 	for(int i = 0; i<NR_TABLE_LOCKS; i++)
 		MT_lock_init(&store->table_locks[i], "sqlstore_table");
 	for(int i = 0; i<NR_COLUMN_LOCKS; i++)
@@ -3225,6 +3215,7 @@ func_dup(sql_trans *tr, sql_func *of, sq
 	f->query = (of->query)?SA_STRDUP(sa, of->query):NULL;
 	f->s = s;
 	f->sa = sa;
+	MT_lock_init(&f->function_lock, "function_lock");
 
 	f->ops = SA_LIST(sa, (fdestroy) &arg_destroy);
 	for (node *n=of->ops->h; n; n = n->next)
@@ -4848,6 +4839,8 @@ create_sql_func(sqlstore *store, sql_all
 	t->fix_scale = SCALE_EQ;
 	t->s = NULL;
 	t->system = system;
+	if (!t->instantiated)
+		MT_lock_init(&t->function_lock, "function_lock");
 	return t;
 }
 
@@ -4885,6 +4878,8 @@ sql_trans_create_func(sql_func **fres, s
 	}
 	t->query = (query)?SA_STRDUP(tr->sa, query):NULL;
 	t->s = s;
+	if (!t->instantiated)
+		MT_lock_init(&t->function_lock, "function_lock");
 
 	if ((res = os_add(s->funcs, tr, t->base.name, &t->base)))
 		return res;
--- a/sql/storage/store_sequence.c
+++ b/sql/storage/store_sequence.c
@@ -161,7 +161,7 @@ seqbulk_next_value(sql_store store, sql_
 	lng start_index = 0;
 
 	if (!s->called) {
-		s->cur = seq->start;
+		s->cur = isNew(seq) ? seq->start : s->cached;
 		*dest = s->cur;
 		start_index = 1;
 		s->called = 1;
@@ -169,48 +169,75 @@ seqbulk_next_value(sql_store store, sql_
 
 	lng min = seq->minvalue;
 	lng max = seq->maxvalue;
+	lng cur = s->cur;
 
+	bool store_unlocked = false;
 	if (seq->increment > 0) {
 		lng inc = seq->increment; // new value = old value + inc;
+
+		if (start_index < cnt && !seq->cycle && !(max > 0 && s->cur < 0)) {
+			if ((max -s->cur) / (cnt - start_index) >= inc) {
+				s->cur += inc * (cnt - start_index);
+				lng old_cached = s->cached;
+				s->cached = calculate_new_cached_value(s->cur, seq->increment, seq->cacheinc, min, max);
+
+				if (old_cached != s->cached)
+					sql_update_sequence_cache(store, seq, s->cached);
+				store_unlock(store);
+				store_unlocked = true;
+			}
+			else {
+				store_unlock(store);
+				return 0;
+			}
+		}
 		for(lng i = start_index; i < cnt; i++) {
-			if ((GDK_lng_max - inc < s->cur) || ((s->cur += inc) > max)) {
+			if ((GDK_lng_max - inc < cur) || ((cur += inc) > max)) {
 				// overflow
-				if (seq->cycle) {
-					s->cur = min;
-				}
-				else {
-					store_unlock(store);
-					return 0;
-				}
+				assert(seq->cycle);
+				cur = min;
 			}
-			dest[i] = s->cur;
+			dest[i] = cur;
 		}
 	}
 	else { // seq->increment < 0
-		lng inc = -seq->increment; // new value = old value - inc;		
+		lng inc = -seq->increment; // new value = old value - inc;
+
+		if (start_index < cnt && !seq->cycle && !(min < 0 && s->cur > 0)) {
+			if ((s->cur - min) / (cnt - start_index) >= inc) {
+				s->cur -= inc * (cnt - start_index);
+				lng old_cached = s->cached;
+				s->cached = calculate_new_cached_value(s->cur, seq->increment, seq->cacheinc, min, max);
+
+				if (old_cached != s->cached)
+					sql_update_sequence_cache(store, seq, s->cached);
+				store_unlock(store);
+				store_unlocked = true;
+			}
+			else {
+				store_unlock(store);
+				return 0;
+			}
+		}
 		for(lng i = start_index; i < cnt; i++) {
-			if ((-GDK_lng_max + inc > s->cur) || ((s->cur -= inc)  < min)) {
+			if ((-GDK_lng_max + inc > cur) || ((cur -= inc)  < min)) {
 				// underflow
-				if (seq->cycle) {
-					s->cur = max;
-				}
-				else {
-					store_unlock(store);
-					return 0;
-				}
+				assert(seq->cycle);
+				cur = max;
 			}
-			dest[i] = s->cur;
+			dest[i] = cur;
 		}
 	}
 
-	lng old_cached = s->cached;
-	s->cached = calculate_new_cached_value(s->cur, seq->increment, seq->cacheinc, min, max);
+	if (!store_unlocked) {
+		s->cur = cur;
+		lng old_cached = s->cached;
+		s->cached = calculate_new_cached_value(s->cur, seq->increment, seq->cacheinc, min, max);
 
-	if (old_cached != s->cached) {
-		sql_update_sequence_cache(store, seq, s->cached);
+		if (old_cached != s->cached)
+			sql_update_sequence_cache(store, seq, s->cached);
+		store_unlock(store);
 	}
-
-	store_unlock(store);
 	return 1;
 }
 
@@ -244,8 +271,8 @@ seq_get_value(sql_store store, sql_seque
 		s = n->data;
 	}
 
-	*val = s->cur; 
-		
+	*val = s->called ? s->cur : lng_nil;
+
 	store_unlock(store);
 	return 1;
 }
@@ -276,16 +303,9 @@ seq_peak_next_value(sql_store store, sql
 	}
 
 	if (!s->called) {
-		if (isNew(seq)) {
-			*val = seq->start;
-			store_unlock(store);
-			return 1;
-		}
-		else {
-			*val = s->cached;
-			store_unlock(store);
-			return 1;
-		}
+		*val = isNew(seq) ? seq->start : s->cached;
+		store_unlock(store);
+		return 1;
 	}
 
 	lng min = seq->minvalue;
--- a/sql/test/BugTracker-2018/Tests/alter-sequence-subquery.Bug-6657.test
+++ b/sql/test/BugTracker-2018/Tests/alter-sequence-subquery.Bug-6657.test
@@ -4,6 +4,11 @@ create sequence "testme" as integer star
 query I rowsort
 select get_value_for('sys', 'testme')
 ----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys', 'testme')
+----
 2
 
 statement ok
@@ -12,6 +17,11 @@ alter sequence "testme" restart with (se
 query I rowsort
 select get_value_for('sys', 'testme')
 ----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys', 'testme')
+----
 1
 
 statement error
@@ -20,7 +30,7 @@ alter sequence "testme" restart with (se
 query I rowsort
 select get_value_for('sys', 'testme')
 ----
-1
+NULL
 
 statement ok
 drop sequence "testme"
--- a/sql/test/BugTracker-2018/Tests/negative-sequences.Bug-6665.test
+++ b/sql/test/BugTracker-2018/Tests/negative-sequences.Bug-6665.test
@@ -7,6 +7,11 @@ create sequence "other_seq" as integer s
 query I rowsort
 select get_value_for('sys', 'other_seq')
 ----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys', 'other_seq')
+----
 -300
 
 query I rowsort
@@ -19,6 +24,11 @@ select next value for "other_seq"
 ----
 -320
 
+query I rowsort
+select peak_next_value_for('sys', 'other_seq')
+----
+-340
+
 statement ok
 create table "testme" ("col1" int default next value for "other_seq", "col2" int)
 
@@ -46,6 +56,11 @@ alter sequence "other_seq" restart with 
 query I rowsort
 select get_value_for('sys', 'other_seq')
 ----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys', 'other_seq')
+----
 -400
 
 query I rowsort
--- a/sql/test/BugTracker-2019/Tests/sequence-first-next-value.Bug-6743.test
+++ b/sql/test/BugTracker-2019/Tests/sequence-first-next-value.Bug-6743.test
@@ -4,10 +4,20 @@ create sequence seq as int
 query I rowsort
 select get_value_for('sys','seq')
 ----
+NULL
+
+query I rowsort
+select get_value_for('sys','seq')
+----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys','seq')
+----
 1
 
 query I rowsort
-select get_value_for('sys','seq')
+select peak_next_value_for('sys','seq')
 ----
 1
 
@@ -51,6 +61,16 @@ select get_value_for('sys','seq')
 ----
 4
 
+query I rowsort
+select peak_next_value_for('sys','seq')
+----
+5
+
+query I rowsort
+select peak_next_value_for('sys','seq')
+----
+5
+
 statement ok
 drop sequence seq
 
@@ -63,10 +83,20 @@ create sequence seq as int
 query I rowsort
 select get_value_for('sys','seq')
 ----
+NULL
+
+query I rowsort
+select get_value_for('sys','seq')
+----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys','seq')
+----
 1
 
 query I rowsort
-select get_value_for('sys','seq')
+select peak_next_value_for('sys','seq')
 ----
 1
 
@@ -110,6 +140,16 @@ select get_value_for('sys','seq')
 ----
 4
 
+query I rowsort
+select peak_next_value_for('sys','seq')
+----
+5
+
+query I rowsort
+select peak_next_value_for('sys','seq')
+----
+5
+
 statement ok
 rollback
 
--- a/sql/test/BugTracker-2019/Tests/sequences-defaults.Bug-6744.test
+++ b/sql/test/BugTracker-2019/Tests/sequences-defaults.Bug-6744.test
@@ -36,7 +36,7 @@ create sequence seq0 CYCLE
 
 query TIIIIII rowsort
 select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
-where name in ('seq', 'seq1', 'seq2', 'seq3', 'seq4', 'seq5', 'seq6', 'seq7', 'seq8', 'seq9', 'seq0')
+where name in ('seq')
 ----
 seq
 1
@@ -45,6 +45,11 @@ 9223372036854775807
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq0')
+----
 seq0
 1
 0
@@ -52,6 +57,11 @@ 9223372036854775807
 1
 1
 1
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq1')
+----
 seq1
 1
 0
@@ -59,6 +69,11 @@ 9223372036854775807
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq2')
+----
 seq2
 2
 0
@@ -66,6 +81,11 @@ 9223372036854775807
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq3')
+----
 seq3
 1
 0
@@ -73,6 +93,11 @@ 9223372036854775807
 3
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq4')
+----
 seq4
 4
 4
@@ -80,13 +105,23 @@ 9223372036854775807
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq5')
+----
 seq5
 1
-0
+-9223372036854775807
 9223372036854775807
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq6')
+----
 seq6
 1
 0
@@ -94,13 +129,23 @@ 6
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq7')
+----
 seq7
 1
 0
-0
+9223372036854775807
 1
 1
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq8')
+----
 seq8
 1
 0
@@ -108,6 +153,11 @@ 9223372036854775807
 1
 8
 0
+
+query TIIIIII rowsort
+select name, start, minvalue, maxvalue, increment, cacheinc, cycle from sequences
+where name in ('seq9')
+----
 seq9
 1
 0
--- a/sql/test/dict/Tests/All
+++ b/sql/test/dict/Tests/All
@@ -1,1 +1,2 @@
 dict01
+dict02
--- a/sql/test/dict/Tests/dict01.test
+++ b/sql/test/dict/Tests/dict01.test
@@ -41,12 +41,6 @@ statement ok
 START TRANSACTION
 
 statement ok
-DROP ALL PROCEDURE "sys"."dict_compress"
-
-statement ok
-DROP ALL PROCEDURE "sys"."for_compress"
-
-statement ok
 DROP TABLE "mct20"
 
 statement ok
@@ -54,3 +48,73 @@ DROP TABLE "mct21"
 
 statement ok
 COMMIT
+
+statement ok
+START TRANSACTION
+
+statement ok
+CREATE TABLE "t1" ("c0" UUID,"c1" SMALLINT NOT NULL)
+
+statement ok rowcount 9
+COPY 9 RECORDS INTO "t1" FROM stdin USING DELIMITERS E'\t',E'\n','"'
+<COPY_INTO_DATA>
+c036a4cf-ecec-57d1-9aca-6dce4eb8d12b	5
+df1bcbac-01e3-81bc-a7c2-c2769fc9751a	0
+NULL	7
+NULL	9
+NULL	1
+NULL	3
+bb4fb0da-aff1-1919-f4eb-abaaf9e6b1f7	6
+648be74d-ccff-ea44-fd64-dfcb3a8c5b6c	8
+fb7c955a-defd-1b91-0aca-aecfc8a0c5aa	2
+
+statement ok
+CREATE TABLE "t0" ("c0" BIGINT NOT NULL)
+
+statement ok rowcount 11
+COPY 11 RECORDS INTO "sys"."t0" FROM stdin USING DELIMITERS E'\t',E'\n','"'
+<COPY_INTO_DATA>
+1
+5
+3
+8
+-1
+9
+4
+2
+6
+0
+7
+
+statement ok
+COMMIT
+
+statement ok
+CALL "sys"."dict_compress"('sys','t0','c0',false)
+
+statement ok rowcount 11
+INSERT INTO t1(c0, c1)(SELECT UUID '7A4A6b8b-e7f9-FA09-5650-6d1c83B1fc69', t0.c0 FROM t0)
+
+statement ok
+START TRANSACTION
+
+statement ok
+DROP TABLE "t0"
+
+statement ok
+DROP TABLE "t1"
+
+statement ok
+COMMIT
+
+statement ok
+START TRANSACTION
+
+statement ok
+DROP ALL PROCEDURE "sys"."dict_compress"
+
+statement ok
+DROP ALL PROCEDURE "sys"."for_compress"
+
+statement ok
+COMMIT
new file mode 100644
--- /dev/null
+++ b/sql/test/dict/Tests/dict02.SQL.py
@@ -0,0 +1,31 @@
+import os
+
+from MonetDBtesting.sqltest import SQLTestCase
+
+port = os.environ['MAPIPORT']
+db = os.environ['TSTDB']
+
+with SQLTestCase() as cli:
+    cli.connect(username="monetdb", password="monetdb")
+    cli.execute("""
+    START TRANSACTION;
+    CREATE TABLE "mct00" ("c0" TINYINT,"c1" BOOLEAN);
+    INSERT INTO "mct00" VALUES (4, true), (NULL, false);
+    create procedure "sys"."dict_compress"(sname string, tname string, cname string, ordered_values bool) external name "dict"."compress";
+    COMMIT;
+
+    CALL "sys"."dict_compress"('sys','mct00','c1',true);
+    CREATE REMOTE TABLE "rmct00" ("c0" TINYINT,"c1" BOOLEAN) ON 'mapi:monetdb://localhost:%s/%s/sys/mct00';
+    """ % (port, db)).assertSucceeded()
+
+    cli.execute('SELECT mct00.c1 FROM mct00;') \
+        .assertSucceeded().assertDataResultMatch([(True,),(False,)])
+    cli.execute('SELECT rmct00.c1 FROM rmct00') \
+        .assertSucceeded().assertDataResultMatch([(True,),(False,)])
+
+    cli.execute("""
+    START TRANSACTION;
+    DROP TABLE rmct00;
+    DROP TABLE mct00;
+    DROP PROCEDURE "sys"."dict_compress";
+    COMMIT;""").assertSucceeded()
--- a/sql/test/emptydb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.int128
+++ b/sql/test/emptydb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.int128
@@ -4681,7 +4681,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.ppc64.int128
+++ b/sql/test/emptydb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.ppc64.int128
@@ -4681,7 +4681,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out
+++ b/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.32bit
+++ b/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.32bit
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.int128
+++ b/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.int128
@@ -4752,7 +4752,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.ppc64
+++ b/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.ppc64
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.ppc64.int128
+++ b/sql/test/emptydb-previous-upgrade-chain/Tests/upgrade.stable.out.ppc64.int128
@@ -4752,7 +4752,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade-hge/Tests/upgrade.stable.out.int128
+++ b/sql/test/emptydb-previous-upgrade-hge/Tests/upgrade.stable.out.int128
@@ -4681,7 +4681,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out
+++ b/sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out.32bit
+++ b/sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out.32bit
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out.int128
+++ b/sql/test/emptydb-previous-upgrade/Tests/upgrade.stable.out.int128
@@ -4752,7 +4752,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/emptydb/Tests/check.stable.out
+++ b/sql/test/emptydb/Tests/check.stable.out
@@ -1044,7 +1044,7 @@ create view sys.describe_functions as wi
 create view sys.describe_indices as with it (id, idx) as (values (0, 'INDEX'), (4, 'IMPRINTS INDEX'), (5, 'ORDERED INDEX')) select i.name ind, s.name sch, t.name tbl, c.name col, it.idx tpe from sys.idxs as i left join sys.keys as k on i.name = k.name, sys.objects as kc, sys._columns as c, sys.schemas s, sys._tables as t, it where i.table_id = t.id and i.id = kc.id and kc.name = c.name and t.id = c.table_id and t.schema_id = s.id and k.type is null and i.type = it.id order by i.name, kc.nr;
 create view sys.describe_partition_tables as select m_sch, m_tbl, p_sch, p_tbl, case when p_raw_type is null then 'READ ONLY' when (p_raw_type = 'VALUES' and pvalues is null) or (p_raw_type = 'RANGE' and minimum is null and maximum is null and with_nulls) then 'FOR NULLS' else p_raw_type end as tpe, pvalues, minimum, maximum, with_nulls from (with tp("type", table_id) as (select ifthenelse((table_partitions."type" & 2) = 2, 'VALUES', 'RANGE'), table_partitions.table_id from sys.table_partitions), subq(m_tid, p_mid, "type", m_sch, m_tbl, p_sch, p_tbl) as (select m_t.id, p_m.id, m_t."type", m_s.name, m_t.name, p_s.name, p_m.name from sys.schemas m_s, sys._tables m_t, sys.dependencies d, sys.schemas p_s, sys._tables p_m where m_t."type" in (3, 6) and m_t.schema_id = m_s.id and m_s.name <> 'tmp' and m_t.system = false and m_t.id = d.depend_id and d.id = p_m.id and p_m.schema_id = p_s.id order by m_t.id, p_m.id) select subq.m_sch, subq.m_tbl, subq.p_sch, subq.p_tbl, tp."type" as p_raw_type, case when tp."type" = 'VALUES' then (select group_concat(vp.value, ',') from sys.value_partitions vp where vp.table_id = subq.p_mid) else null end as pvalues, case when tp."type" = 'RANGE' then (select minimum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as minimum, case when tp."type" = 'RANGE' then (select maximum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as maximum, case when tp."type" = 'VALUES' then exists(select vp.value from sys.value_partitions vp where vp.table_id = subq.p_mid and vp.value is null) else (select rp.with_nulls from sys.range_partitions rp where rp.table_id = subq.p_mid) end as with_nulls from subq left outer join tp on subq.m_tid = tp.table_id) as tmp_pi;
 create view sys.describe_privileges as select case when o.tpe is null and pc.privilege_code_name = 'SELECT' then 'COPY FROM' when o.tpe is null and pc.privilege_code_name = 'UPDATE' then 'COPY INTO' else o.nme end o_nme, coalesce(o.tpe, 'GLOBAL') o_tpe, pc.privilege_code_name p_nme, a.name a_nme, g.name g_nme, p.grantable grantable from sys.privileges p left join (select t.id, s.name || '.' || t.name , 'TABLE' from sys.schemas s, sys.tables t where s.id = t.schema_id union all select c.id, s.name || '.' || t.name || '.' || c.name, 'COLUMN' from sys.schemas s, sys.tables t, sys.columns c where s.id = t.schema_id and t.id = c.table_id union all select f.id, f.nme, f.tpe from sys.fully_qualified_functions f) o(id, nme, tpe) on o.id = p.obj_id, sys.privilege_codes pc, auths a, auths g where p.privileges = pc.privilege_code_id and p.auth_id = a.id and p.grantor = g.id;
-create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq."start" s, get_value_for(s.name, seq.name) as rs, seq."minvalue" mi, seq."maxvalue" ma, seq."increment" inc, seq."cacheinc" cache, seq."cycle" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;
+create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq."start" s, peak_next_value_for(s.name, seq.name) as rs, seq."minvalue" mi, seq."maxvalue" ma, seq."increment" inc, seq."cacheinc" cache, seq."cycle" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;
 create view sys.describe_tables as select t.id o, s.name sch, t.name tab, ts.table_type_name typ, (select ' (' || group_concat(sys.dq(c.name) || ' ' || sys.describe_type(c.type, c.type_digits, c.type_scale) || ifthenelse(c."null" = 'false', ' NOT NULL', '') , ', ') || ')' from sys._columns c where c.table_id = t.id) col, case ts.table_type_name when 'REMOTE TABLE' then sys.get_remote_table_expressions(s.name, t.name) when 'MERGE TABLE' then sys.get_merge_table_partition_expressions(t.id) when 'VIEW' then sys.schema_guard(s.name, t.name, t.query) else '' end opt from sys.schemas s, sys.table_types ts, sys.tables t where ts.table_type_name in ('TABLE', 'VIEW', 'MERGE TABLE', 'REMOTE TABLE', 'REPLICA TABLE') and t.system = false and s.id = t.schema_id and ts.table_type_id = t.type and s.name <> 'tmp';
 create view sys.describe_triggers as select s.name sch, t.name tab, tr.name tri, tr.statement def from sys.schemas s, sys.tables t, sys.triggers tr where s.id = t.schema_id and t.id = tr.table_id and not t.system;
 create view sys.describe_user_defined_types as select s.name sch, t.sqlname sql_tpe, t.systemname ext_tpe from sys.types t join sys.schemas s on t.schema_id = s.id where t.eclass = 18 and ((s.name = 'sys' and t.sqlname not in ('geometrya', 'mbr', 'url', 'inet', 'json', 'uuid', 'xml')) or (s.name <> 'sys'));
@@ -1990,7 +1990,7 @@ select 'null in value_partitions.value',
 [ "sys._tables",	"sys",	"describe_indices",	"create view sys.describe_indices as with it (id, idx) as (values (0, 'INDEX'), (4, 'IMPRINTS INDEX'), (5, 'ORDERED INDEX')) select i.name ind, s.name sch, t.name tbl, c.name col, it.idx tpe from sys.idxs as i left join sys.keys as k on i.name = k.name, sys.objects as kc, sys._columns as c, sys.schemas s, sys._tables as t, it where i.table_id = t.id and i.id = kc.id and kc.name = c.name and t.id = c.table_id and t.schema_id = s.id and k.type is null and i.type = it.id order by i.name, kc.nr;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_partition_tables",	"create view sys.describe_partition_tables as select m_sch, m_tbl, p_sch, p_tbl, case when p_raw_type is null then 'READ ONLY' when (p_raw_type = 'VALUES' and pvalues is null) or (p_raw_type = 'RANGE' and minimum is null and maximum is null and with_nulls) then 'FOR NULLS' else p_raw_type end as tpe, pvalues, minimum, maximum, with_nulls from (with tp(\"type\", table_id) as (select ifthenelse((table_partitions.\"type\" & 2) = 2, 'VALUES', 'RANGE'), table_partitions.table_id from sys.table_partitions), subq(m_tid, p_mid, \"type\", m_sch, m_tbl, p_sch, p_tbl) as (select m_t.id, p_m.id, m_t.\"type\", m_s.name, m_t.name, p_s.name, p_m.name from sys.schemas m_s, sys._tables m_t, sys.dependencies d, sys.schemas p_s, sys._tables p_m where m_t.\"type\" in (3, 6) and m_t.schema_id = m_s.id and m_s.name <> 'tmp' and m_t.system = false and m_t.id = d.depend_id and d.id = p_m.id and p_m.schema_id = p_s.id order by m_t.id, p_m.id) select subq.m_sch, subq.m_tbl, subq.p_sch, subq.p_tbl, tp.\"type\" as p_raw_type, case when tp.\"type\" = 'VALUES' then (select group_concat(vp.value, ',') from sys.value_partitions vp where vp.table_id = subq.p_mid) else null end as pvalues, case when tp.\"type\" = 'RANGE' then (select minimum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as minimum, case when tp.\"type\" = 'RANGE' then (select maximum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as maximum, case when tp.\"type\" = 'VALUES' then exists(select vp.value from sys.value_partitions vp where vp.table_id = subq.p_mid and vp.value is null) else (select rp.with_nulls from sys.range_partitions rp where rp.table_id = subq.p_mid) end as with_nulls from subq left outer join tp on subq.m_tid = tp.table_id) as tmp_pi;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_privileges",	"create view sys.describe_privileges as select case when o.tpe is null and pc.privilege_code_name = 'SELECT' then 'COPY FROM' when o.tpe is null and pc.privilege_code_name = 'UPDATE' then 'COPY INTO' else o.nme end o_nme, coalesce(o.tpe, 'GLOBAL') o_tpe, pc.privilege_code_name p_nme, a.name a_nme, g.name g_nme, p.grantable grantable from sys.privileges p left join (select t.id, s.name || '.' || t.name , 'TABLE' from sys.schemas s, sys.tables t where s.id = t.schema_id union all select c.id, s.name || '.' || t.name || '.' || c.name, 'COLUMN' from sys.schemas s, sys.tables t, sys.columns c where s.id = t.schema_id and t.id = c.table_id union all select f.id, f.nme, f.tpe from sys.fully_qualified_functions f) o(id, nme, tpe) on o.id = p.obj_id, sys.privilege_codes pc, auths a, auths g where p.privileges = pc.privilege_code_id and p.auth_id = a.id and p.grantor = g.id;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
-[ "sys._tables",	"sys",	"describe_sequences",	"create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq.\"start\" s, get_value_for(s.name, seq.name) as rs, seq.\"minvalue\" mi, seq.\"maxvalue\" ma, seq.\"increment\" inc, seq.\"cacheinc\" cache, seq.\"cycle\" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
+[ "sys._tables",	"sys",	"describe_sequences",	"create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq.\"start\" s, peak_next_value_for(s.name, seq.name) as rs, seq.\"minvalue\" mi, seq.\"maxvalue\" ma, seq.\"increment\" inc, seq.\"cacheinc\" cache, seq.\"cycle\" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_tables",	"create view sys.describe_tables as select t.id o, s.name sch, t.name tab, ts.table_type_name typ, (select ' (' || group_concat(sys.dq(c.name) || ' ' || sys.describe_type(c.type, c.type_digits, c.type_scale) || ifthenelse(c.\"null\" = 'false', ' NOT NULL', '') , ', ') || ')' from sys._columns c where c.table_id = t.id) col, case ts.table_type_name when 'REMOTE TABLE' then sys.get_remote_table_expressions(s.name, t.name) when 'MERGE TABLE' then sys.get_merge_table_partition_expressions(t.id) when 'VIEW' then sys.schema_guard(s.name, t.name, t.query) else '' end opt from sys.schemas s, sys.table_types ts, sys.tables t where ts.table_type_name in ('TABLE', 'VIEW', 'MERGE TABLE', 'REMOTE TABLE', 'REPLICA TABLE') and t.system = false and s.id = t.schema_id and ts.table_type_id = t.type and s.name <> 'tmp';",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_triggers",	"create view sys.describe_triggers as select s.name sch, t.name tab, tr.name tri, tr.statement def from sys.schemas s, sys.tables t, sys.triggers tr where s.id = t.schema_id and t.id = tr.table_id and not t.system;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_user_defined_types",	"create view sys.describe_user_defined_types as select s.name sch, t.sqlname sql_tpe, t.systemname ext_tpe from sys.types t join sys.schemas s on t.schema_id = s.id where t.eclass = 18 and ((s.name = 'sys' and t.sqlname not in ('geometrya', 'mbr', 'url', 'inet', 'json', 'uuid', 'xml')) or (s.name <> 'sys'));",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
--- a/sql/test/emptydb/Tests/check.stable.out.32bit
+++ b/sql/test/emptydb/Tests/check.stable.out.32bit
@@ -1044,7 +1044,7 @@ create view sys.describe_functions as wi
 create view sys.describe_indices as with it (id, idx) as (values (0, 'INDEX'), (4, 'IMPRINTS INDEX'), (5, 'ORDERED INDEX')) select i.name ind, s.name sch, t.name tbl, c.name col, it.idx tpe from sys.idxs as i left join sys.keys as k on i.name = k.name, sys.objects as kc, sys._columns as c, sys.schemas s, sys._tables as t, it where i.table_id = t.id and i.id = kc.id and kc.name = c.name and t.id = c.table_id and t.schema_id = s.id and k.type is null and i.type = it.id order by i.name, kc.nr;
 create view sys.describe_partition_tables as select m_sch, m_tbl, p_sch, p_tbl, case when p_raw_type is null then 'READ ONLY' when (p_raw_type = 'VALUES' and pvalues is null) or (p_raw_type = 'RANGE' and minimum is null and maximum is null and with_nulls) then 'FOR NULLS' else p_raw_type end as tpe, pvalues, minimum, maximum, with_nulls from (with tp("type", table_id) as (select ifthenelse((table_partitions."type" & 2) = 2, 'VALUES', 'RANGE'), table_partitions.table_id from sys.table_partitions), subq(m_tid, p_mid, "type", m_sch, m_tbl, p_sch, p_tbl) as (select m_t.id, p_m.id, m_t."type", m_s.name, m_t.name, p_s.name, p_m.name from sys.schemas m_s, sys._tables m_t, sys.dependencies d, sys.schemas p_s, sys._tables p_m where m_t."type" in (3, 6) and m_t.schema_id = m_s.id and m_s.name <> 'tmp' and m_t.system = false and m_t.id = d.depend_id and d.id = p_m.id and p_m.schema_id = p_s.id order by m_t.id, p_m.id) select subq.m_sch, subq.m_tbl, subq.p_sch, subq.p_tbl, tp."type" as p_raw_type, case when tp."type" = 'VALUES' then (select group_concat(vp.value, ',') from sys.value_partitions vp where vp.table_id = subq.p_mid) else null end as pvalues, case when tp."type" = 'RANGE' then (select minimum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as minimum, case when tp."type" = 'RANGE' then (select maximum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as maximum, case when tp."type" = 'VALUES' then exists(select vp.value from sys.value_partitions vp where vp.table_id = subq.p_mid and vp.value is null) else (select rp.with_nulls from sys.range_partitions rp where rp.table_id = subq.p_mid) end as with_nulls from subq left outer join tp on subq.m_tid = tp.table_id) as tmp_pi;
 create view sys.describe_privileges as select case when o.tpe is null and pc.privilege_code_name = 'SELECT' then 'COPY FROM' when o.tpe is null and pc.privilege_code_name = 'UPDATE' then 'COPY INTO' else o.nme end o_nme, coalesce(o.tpe, 'GLOBAL') o_tpe, pc.privilege_code_name p_nme, a.name a_nme, g.name g_nme, p.grantable grantable from sys.privileges p left join (select t.id, s.name || '.' || t.name , 'TABLE' from sys.schemas s, sys.tables t where s.id = t.schema_id union all select c.id, s.name || '.' || t.name || '.' || c.name, 'COLUMN' from sys.schemas s, sys.tables t, sys.columns c where s.id = t.schema_id and t.id = c.table_id union all select f.id, f.nme, f.tpe from sys.fully_qualified_functions f) o(id, nme, tpe) on o.id = p.obj_id, sys.privilege_codes pc, auths a, auths g where p.privileges = pc.privilege_code_id and p.auth_id = a.id and p.grantor = g.id;
-create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq."start" s, get_value_for(s.name, seq.name) as rs, seq."minvalue" mi, seq."maxvalue" ma, seq."increment" inc, seq."cacheinc" cache, seq."cycle" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;
+create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq."start" s, sys.peak_next_value_for(s.name, seq.name) AS rs, seq."minvalue" mi, seq."maxvalue" ma, seq."increment" inc, seq."cacheinc" cache, seq."cycle" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;
 create view sys.describe_tables as select t.id o, s.name sch, t.name tab, ts.table_type_name typ, (select ' (' || group_concat(sys.dq(c.name) || ' ' || sys.describe_type(c.type, c.type_digits, c.type_scale) || ifthenelse(c."null" = 'false', ' NOT NULL', '') , ', ') || ')' from sys._columns c where c.table_id = t.id) col, case ts.table_type_name when 'REMOTE TABLE' then sys.get_remote_table_expressions(s.name, t.name) when 'MERGE TABLE' then sys.get_merge_table_partition_expressions(t.id) when 'VIEW' then sys.schema_guard(s.name, t.name, t.query) else '' end opt from sys.schemas s, sys.table_types ts, sys.tables t where ts.table_type_name in ('TABLE', 'VIEW', 'MERGE TABLE', 'REMOTE TABLE', 'REPLICA TABLE') and t.system = false and s.id = t.schema_id and ts.table_type_id = t.type and s.name <> 'tmp';
 create view sys.describe_triggers as select s.name sch, t.name tab, tr.name tri, tr.statement def from sys.schemas s, sys.tables t, sys.triggers tr where s.id = t.schema_id and t.id = tr.table_id and not t.system;
 create view sys.describe_user_defined_types as select s.name sch, t.sqlname sql_tpe, t.systemname ext_tpe from sys.types t join sys.schemas s on t.schema_id = s.id where t.eclass = 18 and ((s.name = 'sys' and t.sqlname not in ('geometrya', 'mbr', 'url', 'inet', 'json', 'uuid', 'xml')) or (s.name <> 'sys'));
@@ -1990,7 +1990,7 @@ select 'null in value_partitions.value',
 [ "sys._tables",	"sys",	"describe_indices",	"create view sys.describe_indices as with it (id, idx) as (values (0, 'INDEX'), (4, 'IMPRINTS INDEX'), (5, 'ORDERED INDEX')) select i.name ind, s.name sch, t.name tbl, c.name col, it.idx tpe from sys.idxs as i left join sys.keys as k on i.name = k.name, sys.objects as kc, sys._columns as c, sys.schemas s, sys._tables as t, it where i.table_id = t.id and i.id = kc.id and kc.name = c.name and t.id = c.table_id and t.schema_id = s.id and k.type is null and i.type = it.id order by i.name, kc.nr;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_partition_tables",	"create view sys.describe_partition_tables as select m_sch, m_tbl, p_sch, p_tbl, case when p_raw_type is null then 'READ ONLY' when (p_raw_type = 'VALUES' and pvalues is null) or (p_raw_type = 'RANGE' and minimum is null and maximum is null and with_nulls) then 'FOR NULLS' else p_raw_type end as tpe, pvalues, minimum, maximum, with_nulls from (with tp(\"type\", table_id) as (select ifthenelse((table_partitions.\"type\" & 2) = 2, 'VALUES', 'RANGE'), table_partitions.table_id from sys.table_partitions), subq(m_tid, p_mid, \"type\", m_sch, m_tbl, p_sch, p_tbl) as (select m_t.id, p_m.id, m_t.\"type\", m_s.name, m_t.name, p_s.name, p_m.name from sys.schemas m_s, sys._tables m_t, sys.dependencies d, sys.schemas p_s, sys._tables p_m where m_t.\"type\" in (3, 6) and m_t.schema_id = m_s.id and m_s.name <> 'tmp' and m_t.system = false and m_t.id = d.depend_id and d.id = p_m.id and p_m.schema_id = p_s.id order by m_t.id, p_m.id) select subq.m_sch, subq.m_tbl, subq.p_sch, subq.p_tbl, tp.\"type\" as p_raw_type, case when tp.\"type\" = 'VALUES' then (select group_concat(vp.value, ',') from sys.value_partitions vp where vp.table_id = subq.p_mid) else null end as pvalues, case when tp.\"type\" = 'RANGE' then (select minimum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as minimum, case when tp.\"type\" = 'RANGE' then (select maximum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as maximum, case when tp.\"type\" = 'VALUES' then exists(select vp.value from sys.value_partitions vp where vp.table_id = subq.p_mid and vp.value is null) else (select rp.with_nulls from sys.range_partitions rp where rp.table_id = subq.p_mid) end as with_nulls from subq left outer join tp on subq.m_tid = tp.table_id) as tmp_pi;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_privileges",	"create view sys.describe_privileges as select case when o.tpe is null and pc.privilege_code_name = 'SELECT' then 'COPY FROM' when o.tpe is null and pc.privilege_code_name = 'UPDATE' then 'COPY INTO' else o.nme end o_nme, coalesce(o.tpe, 'GLOBAL') o_tpe, pc.privilege_code_name p_nme, a.name a_nme, g.name g_nme, p.grantable grantable from sys.privileges p left join (select t.id, s.name || '.' || t.name , 'TABLE' from sys.schemas s, sys.tables t where s.id = t.schema_id union all select c.id, s.name || '.' || t.name || '.' || c.name, 'COLUMN' from sys.schemas s, sys.tables t, sys.columns c where s.id = t.schema_id and t.id = c.table_id union all select f.id, f.nme, f.tpe from sys.fully_qualified_functions f) o(id, nme, tpe) on o.id = p.obj_id, sys.privilege_codes pc, auths a, auths g where p.privileges = pc.privilege_code_id and p.auth_id = a.id and p.grantor = g.id;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
-[ "sys._tables",	"sys",	"describe_sequences",	"create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq.\"start\" s, get_value_for(s.name, seq.name) as rs, seq.\"minvalue\" mi, seq.\"maxvalue\" ma, seq.\"increment\" inc, seq.\"cacheinc\" cache, seq.\"cycle\" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
+[ "sys._tables",	"sys",	"describe_sequences",	"create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq.\"start\" s, sys.peak_next_value_for(s.name, seq.name) AS rs, seq.\"minvalue\" mi, seq.\"maxvalue\" ma, seq.\"increment\" inc, seq.\"cacheinc\" cache, seq.\"cycle\" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_tables",	"create view sys.describe_tables as select t.id o, s.name sch, t.name tab, ts.table_type_name typ, (select ' (' || group_concat(sys.dq(c.name) || ' ' || sys.describe_type(c.type, c.type_digits, c.type_scale) || ifthenelse(c.\"null\" = 'false', ' NOT NULL', '') , ', ') || ')' from sys._columns c where c.table_id = t.id) col, case ts.table_type_name when 'REMOTE TABLE' then sys.get_remote_table_expressions(s.name, t.name) when 'MERGE TABLE' then sys.get_merge_table_partition_expressions(t.id) when 'VIEW' then sys.schema_guard(s.name, t.name, t.query) else '' end opt from sys.schemas s, sys.table_types ts, sys.tables t where ts.table_type_name in ('TABLE', 'VIEW', 'MERGE TABLE', 'REMOTE TABLE', 'REPLICA TABLE') and t.system = false and s.id = t.schema_id and ts.table_type_id = t.type and s.name <> 'tmp';",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_triggers",	"create view sys.describe_triggers as select s.name sch, t.name tab, tr.name tri, tr.statement def from sys.schemas s, sys.tables t, sys.triggers tr where s.id = t.schema_id and t.id = tr.table_id and not t.system;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_user_defined_types",	"create view sys.describe_user_defined_types as select s.name sch, t.sqlname sql_tpe, t.systemname ext_tpe from sys.types t join sys.schemas s on t.schema_id = s.id where t.eclass = 18 and ((s.name = 'sys' and t.sqlname not in ('geometrya', 'mbr', 'url', 'inet', 'json', 'uuid', 'xml')) or (s.name <> 'sys'));",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
--- a/sql/test/emptydb/Tests/check.stable.out.int128
+++ b/sql/test/emptydb/Tests/check.stable.out.int128
@@ -1044,7 +1044,7 @@ create view sys.describe_functions as wi
 create view sys.describe_indices as with it (id, idx) as (values (0, 'INDEX'), (4, 'IMPRINTS INDEX'), (5, 'ORDERED INDEX')) select i.name ind, s.name sch, t.name tbl, c.name col, it.idx tpe from sys.idxs as i left join sys.keys as k on i.name = k.name, sys.objects as kc, sys._columns as c, sys.schemas s, sys._tables as t, it where i.table_id = t.id and i.id = kc.id and kc.name = c.name and t.id = c.table_id and t.schema_id = s.id and k.type is null and i.type = it.id order by i.name, kc.nr;
 create view sys.describe_partition_tables as select m_sch, m_tbl, p_sch, p_tbl, case when p_raw_type is null then 'READ ONLY' when (p_raw_type = 'VALUES' and pvalues is null) or (p_raw_type = 'RANGE' and minimum is null and maximum is null and with_nulls) then 'FOR NULLS' else p_raw_type end as tpe, pvalues, minimum, maximum, with_nulls from (with tp("type", table_id) as (select ifthenelse((table_partitions."type" & 2) = 2, 'VALUES', 'RANGE'), table_partitions.table_id from sys.table_partitions), subq(m_tid, p_mid, "type", m_sch, m_tbl, p_sch, p_tbl) as (select m_t.id, p_m.id, m_t."type", m_s.name, m_t.name, p_s.name, p_m.name from sys.schemas m_s, sys._tables m_t, sys.dependencies d, sys.schemas p_s, sys._tables p_m where m_t."type" in (3, 6) and m_t.schema_id = m_s.id and m_s.name <> 'tmp' and m_t.system = false and m_t.id = d.depend_id and d.id = p_m.id and p_m.schema_id = p_s.id order by m_t.id, p_m.id) select subq.m_sch, subq.m_tbl, subq.p_sch, subq.p_tbl, tp."type" as p_raw_type, case when tp."type" = 'VALUES' then (select group_concat(vp.value, ',') from sys.value_partitions vp where vp.table_id = subq.p_mid) else null end as pvalues, case when tp."type" = 'RANGE' then (select minimum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as minimum, case when tp."type" = 'RANGE' then (select maximum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as maximum, case when tp."type" = 'VALUES' then exists(select vp.value from sys.value_partitions vp where vp.table_id = subq.p_mid and vp.value is null) else (select rp.with_nulls from sys.range_partitions rp where rp.table_id = subq.p_mid) end as with_nulls from subq left outer join tp on subq.m_tid = tp.table_id) as tmp_pi;
 create view sys.describe_privileges as select case when o.tpe is null and pc.privilege_code_name = 'SELECT' then 'COPY FROM' when o.tpe is null and pc.privilege_code_name = 'UPDATE' then 'COPY INTO' else o.nme end o_nme, coalesce(o.tpe, 'GLOBAL') o_tpe, pc.privilege_code_name p_nme, a.name a_nme, g.name g_nme, p.grantable grantable from sys.privileges p left join (select t.id, s.name || '.' || t.name , 'TABLE' from sys.schemas s, sys.tables t where s.id = t.schema_id union all select c.id, s.name || '.' || t.name || '.' || c.name, 'COLUMN' from sys.schemas s, sys.tables t, sys.columns c where s.id = t.schema_id and t.id = c.table_id union all select f.id, f.nme, f.tpe from sys.fully_qualified_functions f) o(id, nme, tpe) on o.id = p.obj_id, sys.privilege_codes pc, auths a, auths g where p.privileges = pc.privilege_code_id and p.auth_id = a.id and p.grantor = g.id;
-create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq."start" s, get_value_for(s.name, seq.name) as rs, seq."minvalue" mi, seq."maxvalue" ma, seq."increment" inc, seq."cacheinc" cache, seq."cycle" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;
+create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq."start" s, peak_next_value_for(s.name, seq.name) as rs, seq."minvalue" mi, seq."maxvalue" ma, seq."increment" inc, seq."cacheinc" cache, seq."cycle" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;
 create view sys.describe_tables as select t.id o, s.name sch, t.name tab, ts.table_type_name typ, (select ' (' || group_concat(sys.dq(c.name) || ' ' || sys.describe_type(c.type, c.type_digits, c.type_scale) || ifthenelse(c."null" = 'false', ' NOT NULL', '') , ', ') || ')' from sys._columns c where c.table_id = t.id) col, case ts.table_type_name when 'REMOTE TABLE' then sys.get_remote_table_expressions(s.name, t.name) when 'MERGE TABLE' then sys.get_merge_table_partition_expressions(t.id) when 'VIEW' then sys.schema_guard(s.name, t.name, t.query) else '' end opt from sys.schemas s, sys.table_types ts, sys.tables t where ts.table_type_name in ('TABLE', 'VIEW', 'MERGE TABLE', 'REMOTE TABLE', 'REPLICA TABLE') and t.system = false and s.id = t.schema_id and ts.table_type_id = t.type and s.name <> 'tmp';
 create view sys.describe_triggers as select s.name sch, t.name tab, tr.name tri, tr.statement def from sys.schemas s, sys.tables t, sys.triggers tr where s.id = t.schema_id and t.id = tr.table_id and not t.system;
 create view sys.describe_user_defined_types as select s.name sch, t.sqlname sql_tpe, t.systemname ext_tpe from sys.types t join sys.schemas s on t.schema_id = s.id where t.eclass = 18 and ((s.name = 'sys' and t.sqlname not in ('geometrya', 'mbr', 'url', 'inet', 'json', 'uuid', 'xml')) or (s.name <> 'sys'));
@@ -2010,7 +2010,7 @@ select 'null in value_partitions.value',
 [ "sys._tables",	"sys",	"describe_indices",	"create view sys.describe_indices as with it (id, idx) as (values (0, 'INDEX'), (4, 'IMPRINTS INDEX'), (5, 'ORDERED INDEX')) select i.name ind, s.name sch, t.name tbl, c.name col, it.idx tpe from sys.idxs as i left join sys.keys as k on i.name = k.name, sys.objects as kc, sys._columns as c, sys.schemas s, sys._tables as t, it where i.table_id = t.id and i.id = kc.id and kc.name = c.name and t.id = c.table_id and t.schema_id = s.id and k.type is null and i.type = it.id order by i.name, kc.nr;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_partition_tables",	"create view sys.describe_partition_tables as select m_sch, m_tbl, p_sch, p_tbl, case when p_raw_type is null then 'READ ONLY' when (p_raw_type = 'VALUES' and pvalues is null) or (p_raw_type = 'RANGE' and minimum is null and maximum is null and with_nulls) then 'FOR NULLS' else p_raw_type end as tpe, pvalues, minimum, maximum, with_nulls from (with tp(\"type\", table_id) as (select ifthenelse((table_partitions.\"type\" & 2) = 2, 'VALUES', 'RANGE'), table_partitions.table_id from sys.table_partitions), subq(m_tid, p_mid, \"type\", m_sch, m_tbl, p_sch, p_tbl) as (select m_t.id, p_m.id, m_t.\"type\", m_s.name, m_t.name, p_s.name, p_m.name from sys.schemas m_s, sys._tables m_t, sys.dependencies d, sys.schemas p_s, sys._tables p_m where m_t.\"type\" in (3, 6) and m_t.schema_id = m_s.id and m_s.name <> 'tmp' and m_t.system = false and m_t.id = d.depend_id and d.id = p_m.id and p_m.schema_id = p_s.id order by m_t.id, p_m.id) select subq.m_sch, subq.m_tbl, subq.p_sch, subq.p_tbl, tp.\"type\" as p_raw_type, case when tp.\"type\" = 'VALUES' then (select group_concat(vp.value, ',') from sys.value_partitions vp where vp.table_id = subq.p_mid) else null end as pvalues, case when tp.\"type\" = 'RANGE' then (select minimum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as minimum, case when tp.\"type\" = 'RANGE' then (select maximum from sys.range_partitions rp where rp.table_id = subq.p_mid) else null end as maximum, case when tp.\"type\" = 'VALUES' then exists(select vp.value from sys.value_partitions vp where vp.table_id = subq.p_mid and vp.value is null) else (select rp.with_nulls from sys.range_partitions rp where rp.table_id = subq.p_mid) end as with_nulls from subq left outer join tp on subq.m_tid = tp.table_id) as tmp_pi;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_privileges",	"create view sys.describe_privileges as select case when o.tpe is null and pc.privilege_code_name = 'SELECT' then 'COPY FROM' when o.tpe is null and pc.privilege_code_name = 'UPDATE' then 'COPY INTO' else o.nme end o_nme, coalesce(o.tpe, 'GLOBAL') o_tpe, pc.privilege_code_name p_nme, a.name a_nme, g.name g_nme, p.grantable grantable from sys.privileges p left join (select t.id, s.name || '.' || t.name , 'TABLE' from sys.schemas s, sys.tables t where s.id = t.schema_id union all select c.id, s.name || '.' || t.name || '.' || c.name, 'COLUMN' from sys.schemas s, sys.tables t, sys.columns c where s.id = t.schema_id and t.id = c.table_id union all select f.id, f.nme, f.tpe from sys.fully_qualified_functions f) o(id, nme, tpe) on o.id = p.obj_id, sys.privilege_codes pc, auths a, auths g where p.privileges = pc.privilege_code_id and p.auth_id = a.id and p.grantor = g.id;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
-[ "sys._tables",	"sys",	"describe_sequences",	"create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq.\"start\" s, get_value_for(s.name, seq.name) as rs, seq.\"minvalue\" mi, seq.\"maxvalue\" ma, seq.\"increment\" inc, seq.\"cacheinc\" cache, seq.\"cycle\" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
+[ "sys._tables",	"sys",	"describe_sequences",	"create view sys.describe_sequences as select s.name as sch, seq.name as seq, seq.\"start\" s, peak_next_value_for(s.name, seq.name) as rs, seq.\"minvalue\" mi, seq.\"maxvalue\" ma, seq.\"increment\" inc, seq.\"cacheinc\" cache, seq.\"cycle\" cycle from sys.sequences seq, sys.schemas s where s.id = seq.schema_id and s.name <> 'tmp' order by s.name, seq.name;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_tables",	"create view sys.describe_tables as select t.id o, s.name sch, t.name tab, ts.table_type_name typ, (select ' (' || group_concat(sys.dq(c.name) || ' ' || sys.describe_type(c.type, c.type_digits, c.type_scale) || ifthenelse(c.\"null\" = 'false', ' NOT NULL', '') , ', ') || ')' from sys._columns c where c.table_id = t.id) col, case ts.table_type_name when 'REMOTE TABLE' then sys.get_remote_table_expressions(s.name, t.name) when 'MERGE TABLE' then sys.get_merge_table_partition_expressions(t.id) when 'VIEW' then sys.schema_guard(s.name, t.name, t.query) else '' end opt from sys.schemas s, sys.table_types ts, sys.tables t where ts.table_type_name in ('TABLE', 'VIEW', 'MERGE TABLE', 'REMOTE TABLE', 'REPLICA TABLE') and t.system = false and s.id = t.schema_id and ts.table_type_id = t.type and s.name <> 'tmp';",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_triggers",	"create view sys.describe_triggers as select s.name sch, t.name tab, tr.name tri, tr.statement def from sys.schemas s, sys.tables t, sys.triggers tr where s.id = t.schema_id and t.id = tr.table_id and not t.system;",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
 [ "sys._tables",	"sys",	"describe_user_defined_types",	"create view sys.describe_user_defined_types as select s.name sch, t.sqlname sql_tpe, t.systemname ext_tpe from sys.types t join sys.schemas s on t.schema_id = s.id where t.eclass = 18 and ((s.name = 'sys' and t.sqlname not in ('geometrya', 'mbr', 'url', 'inet', 'json', 'uuid', 'xml')) or (s.name <> 'sys'));",	"VIEW",	true,	"COMMIT",	"WRITABLE"	]
--- a/sql/test/miscellaneous/Tests/simple_plans.test
+++ b/sql/test/miscellaneous/Tests/simple_plans.test
@@ -144,6 +144,16 @@ project (
 | ) [ ("tab0"."col1") notin (int(32) "1", int(32) "81") ]
 ) [ tinyint(1) "1" ]
 
+# don't rewrite col2 <> 10 into notin
+query T nosort
+plan select 1 from tab0 where col1 <> 1 and col1 <> 81 and col2 <> 10
+----
+project (
+| select (
+| | table("sys"."tab0") [ "tab0"."col1", "tab0"."col2" ]
+| ) [ ("tab0"."col2") != (int(32) "10"), ("tab0"."col1") notin (int(32) "1", int(32) "81") ]
+) [ tinyint(1) "1" ]
+
 query T nosort
 plan select 1 from tab0 where col1 <> 1 and col1 <> 81 and (col2 < 0)
 ----
--- a/sql/test/sys-schema/Tests/webExamplesMathematicalFunctionsOperators.test
+++ b/sql/test/sys-schema/Tests/webExamplesMathematicalFunctionsOperators.test
@@ -533,6 +533,16 @@ create sequence tst20210325
 query I rowsort
 select get_value_for('sys', 'tst20210325')
 ----
+NULL
+
+query I rowsort
+select peak_next_value_for('sys', 'tst20210325')
+----
+1
+
+query I rowsort
+select peak_next_value_for('sys', 'tst20210325')
+----
 1
 
 query I rowsort
@@ -545,6 +555,21 @@ select get_value_for('sys', 'tst20210325
 ----
 1
 
+query I rowsort
+select get_value_for('sys', 'tst20210325')
+----
+1
+
+query I rowsort
+select peak_next_value_for('sys', 'tst20210325')
+----
+2
+
+query I rowsort
+select peak_next_value_for('sys', 'tst20210325')
+----
+2
+
 statement ok
 drop sequence tst20210325
 
--- a/sql/test/testdb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.int128
+++ b/sql/test/testdb-previous-upgrade-chain-hge/Tests/upgrade.stable.out.int128
@@ -4681,7 +4681,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out
+++ b/sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out.32bit
+++ b/sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out.32bit
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out.int128
+++ b/sql/test/testdb-previous-upgrade-chain/Tests/upgrade.stable.out.int128
@@ -4752,7 +4752,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade-hge/Tests/upgrade.stable.out.int128
+++ b/sql/test/testdb-previous-upgrade-hge/Tests/upgrade.stable.out.int128
@@ -4681,7 +4681,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out
+++ b/sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out.32bit
+++ b/sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out.32bit
@@ -4086,7 +4086,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,
--- a/sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out.int128
+++ b/sql/test/testdb-previous-upgrade/Tests/upgrade.stable.out.int128
@@ -4752,7 +4752,7 @@ CREATE VIEW sys.describe_sequences AS
         s.name as sch,
         seq.name as seq,
         seq."start" s,
-        get_value_for(s.name, seq.name) AS rs,
+        sys.peak_next_value_for(s.name, seq.name) AS rs,
         seq."minvalue" mi,
         seq."maxvalue" ma,
         seq."increment" inc,