first last

This commit is contained in:
l00280231
2021-07-19 10:43:44 +08:00
committed by gentle_hu
parent d9dc69168f
commit cab1715e4b
4 changed files with 318 additions and 9 deletions

View File

@ -268,6 +268,10 @@
"array_recv", 1,
AddBuiltinFunc(_0(2400), _1("array_recv"), _2(3), _3(true), _4(false), _5(array_recv), _6(2277), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(3, 2281, 26, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("array_recv"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))
),
AddFuncGroup(
"array_remove", 1,
AddBuiltinFunc(_0(6555), _1("array_remove"), _2(2), _3(false), _4(false), _5(array_remove), _6(2277), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(2, 2277, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("array_remove"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))
),
AddFuncGroup(
"array_send", 1,
AddBuiltinFunc(_0(2401), _1("array_send"), _2(1), _3(true), _4(false), _5(array_send), _6(17), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(1, 2277), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("array_send"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))

View File

@ -15247,15 +15247,6 @@ upsert_clause:
/* check subquery in set clause*/
ListCell* cell = NULL;
ResTarget* res = NULL;
foreach (cell, $5) {
res = (ResTarget*)lfirst(cell);
if (IsA(res->val,SubLink)) {
ereport(ERROR,
(errmodule(MOD_PARSER),
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Update with subquery is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.")));
}
}
UpsertClause *uc = makeNode(UpsertClause);
uc->targetList = $5;

View File

@ -4559,3 +4559,313 @@ Datum array_unnest(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(funcctx);
}
}
/*
* array_replace/array_remove support
*
* Find all array entries matching (not distinct from) search/search_isnull,
* and delete them if remove is true, else replace them with
* replace/replace_isnull. Comparisons are done using the specified
* collation. fcinfo is passed only for caching purposes.
*/
static ArrayType *
array_replace_internal(ArrayType *array,
Datum search, bool search_isnull,
Datum replace, bool replace_isnull,
bool remove, Oid collation,
FunctionCallInfo fcinfo)
{
ArrayType *result;
Oid element_type;
Datum *values;
bool *nulls;
int *dim;
int ndim;
int nitems,
nresult;
int i;
int32 nbytes = 0;
int32 dataoffset;
bool hasnulls;
int typlen;
bool typbyval;
char typalign;
char *arraydataptr;
bits8 *bitmap;
int bitmask;
bool changed = false;
TypeCacheEntry *typentry;
FunctionCallInfoData locfcinfo;
element_type = ARR_ELEMTYPE(array);
ndim = ARR_NDIM(array);
dim = ARR_DIMS(array);
nitems = ArrayGetNItems(ndim, dim);
/* Return input array unmodified if it is empty */
if (nitems <= 0)
return array;
/*
* We can't remove elements from multi-dimensional arrays, since the
* result might not be rectangular.
*/
if (remove && ndim > 1)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("removing elements from multidimensional arrays is not supported")));
/*
* We arrange to look up the equality function only once per series of
* calls, assuming the element type doesn't change underneath us.
*/
typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
if (typentry == NULL ||
typentry->type_id != element_type)
{
typentry = lookup_type_cache(element_type,
TYPECACHE_EQ_OPR_FINFO);
if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not identify an equality operator for type %s",
format_type_be(element_type))));
fcinfo->flinfo->fn_extra = (void *) typentry;
}
typlen = typentry->typlen;
typbyval = typentry->typbyval;
typalign = typentry->typalign;
/*
* Detoast values if they are toasted. The replacement value must be
* detoasted for insertion into the result array, while detoasting the
* search value only once saves cycles.
*/
if (typlen == -1)
{
if (!search_isnull)
search = PointerGetDatum(PG_DETOAST_DATUM(search));
if (!replace_isnull)
replace = PointerGetDatum(PG_DETOAST_DATUM(replace));
}
/* Prepare to apply the comparison operator */
InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
collation, NULL, NULL);
/* Allocate temporary arrays for new values */
values = (Datum *) palloc(nitems * sizeof(Datum));
nulls = (bool *) palloc(nitems * sizeof(bool));
/* Loop over source data */
arraydataptr = ARR_DATA_PTR(array);
bitmap = ARR_NULLBITMAP(array);
bitmask = 1;
hasnulls = false;
nresult = 0;
for (i = 0; i < nitems; i++)
{
Datum elt;
bool isNull;
bool oprresult;
bool skip = false;
/* Get source element, checking for NULL */
if (bitmap && (*bitmap & bitmask) == 0)
{
isNull = true;
/* If searching for NULL, we have a match */
if (search_isnull)
{
if (remove)
{
skip = true;
changed = true;
}
else if (!replace_isnull)
{
values[nresult] = replace;
isNull = false;
changed = true;
}
}
}
else
{
isNull = false;
elt = fetch_att(arraydataptr, typbyval, typlen);
arraydataptr = att_addlength_datum(arraydataptr, typlen, elt);
arraydataptr = (char *) att_align_nominal(arraydataptr, typalign);
if (search_isnull)
{
/* no match possible, keep element */
values[nresult] = elt;
}
else
{
/* Compare the pair of elements */
locfcinfo.arg[0] = elt;
locfcinfo.arg[1] = search;
locfcinfo.argnull[0] = false;
locfcinfo.argnull[1] = false;
locfcinfo.isnull = false;
oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
if (locfcinfo.isnull || !oprresult)
{
/* no match, keep element */
values[nresult] = elt;
}
else
{
/* match, so replace or delete */
changed = true;
if (remove)
skip = true;
else
{
values[nresult] = replace;
isNull = replace_isnull;
}
}
}
}
if (!skip)
{
nulls[nresult] = isNull;
if (isNull)
hasnulls = true;
else
{
/* Update total result size */
nbytes = att_addlength_datum(nbytes, typlen, values[nresult]);
nbytes = att_align_nominal(nbytes, typalign);
/* check for overflow of total request */
if (!AllocSizeIsValid(nbytes))
ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("array size exceeds the maximum allowed (%d)",
(int) MaxAllocSize)));
}
nresult++;
}
/* advance bitmap pointer if any */
if (bitmap)
{
bitmask <<= 1;
if (bitmask == 0x100)
{
bitmap++;
bitmask = 1;
}
}
}
/*
* If not changed just return the original array
*/
if (!changed)
{
pfree(values);
pfree(nulls);
return array;
}
/* If all elements were removed return an empty array */
if (nresult == 0)
{
pfree(values);
pfree(nulls);
return construct_empty_array(element_type);
}
/* Allocate and initialize the result array */
if (hasnulls)
{
dataoffset = ARR_OVERHEAD_WITHNULLS(ndim, nresult);
nbytes += dataoffset;
}
else
{
dataoffset = 0; /* marker for no null bitmap */
nbytes += ARR_OVERHEAD_NONULLS(ndim);
}
result = (ArrayType *) palloc0(nbytes);
SET_VARSIZE(result, nbytes);
result->ndim = ndim;
result->dataoffset = dataoffset;
result->elemtype = element_type;
memcpy(ARR_DIMS(result), ARR_DIMS(array), ndim * sizeof(int));
memcpy(ARR_LBOUND(result), ARR_LBOUND(array), ndim * sizeof(int));
if (remove)
{
/* Adjust the result length */
ARR_DIMS(result)[0] = nresult;
}
/* Insert data into result array */
CopyArrayEls(result,
values, nulls, nresult,
typlen, typbyval, typalign,
false);
pfree(values);
pfree(nulls);
return result;
}
/*
* Remove any occurrences of an element from an array
*
* If used on a multi-dimensional array this will raise an error.
*/
Datum
array_remove(PG_FUNCTION_ARGS)
{
ArrayType *array;
Datum search = PG_GETARG_DATUM(1);
bool search_isnull = PG_ARGISNULL(1);
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
array = PG_GETARG_ARRAYTYPE_P(0);
array = array_replace_internal(array,
search, search_isnull,
(Datum) 0, true,
true, PG_GET_COLLATION(),
fcinfo);
PG_RETURN_ARRAYTYPE_P(array);
}
/*
* Replace any occurrences of an element in an array
*/
Datum
array_replace(PG_FUNCTION_ARGS)
{
ArrayType *array;
Datum search = PG_GETARG_DATUM(1);
bool search_isnull = PG_ARGISNULL(1);
Datum replace = PG_GETARG_DATUM(2);
bool replace_isnull = PG_ARGISNULL(2);
if (PG_ARGISNULL(0))
PG_RETURN_NULL();
array = PG_GETARG_ARRAYTYPE_P(0);
array = array_replace_internal(array,
search, search_isnull,
replace, replace_isnull,
false, PG_GET_COLLATION(),
fcinfo);
PG_RETURN_ARRAYTYPE_P(array);
}

View File

@ -866,7 +866,11 @@ PlannedStmt* standard_planner(Query* parse, int cursorOptions, ParamListInfo bou
result->query_string = NULL;
result->MaxBloomFilterNum = root->glob->bloomfilter.bloomfilter_index + 1;
/* record which suplan belongs to which thread */
#ifdef ENABLE_MULTIPLE_NODES
if (IS_STREAM_PLAN) {
#else
if (result->num_streams > 0) {
#endif
for (i = 1; i <= list_length(result->subplans); i++)
result->subplan_ids = lappend_int(result->subplan_ids, subplan_ids[i]);
result->initPlan = init_plan;