first last
This commit is contained in:
@ -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'))
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user