From cab1715e4bfc176f47dc404b3477ea0f0f093d4a Mon Sep 17 00:00:00 2001 From: l00280231 Date: Mon, 19 Jul 2021 10:43:44 +0800 Subject: [PATCH] first last --- src/common/backend/catalog/builtin_funcs.ini | 4 + src/common/backend/parser/gram.y | 9 - src/common/backend/utils/adt/arrayfuncs.cpp | 310 +++++++++++++++++++ src/gausskernel/optimizer/plan/planner.cpp | 4 + 4 files changed, 318 insertions(+), 9 deletions(-) diff --git a/src/common/backend/catalog/builtin_funcs.ini b/src/common/backend/catalog/builtin_funcs.ini index 8838097a4..fcd7c882b 100755 --- a/src/common/backend/catalog/builtin_funcs.ini +++ b/src/common/backend/catalog/builtin_funcs.ini @@ -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')) diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 14a26ecd0..64c26729f 100755 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -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; diff --git a/src/common/backend/utils/adt/arrayfuncs.cpp b/src/common/backend/utils/adt/arrayfuncs.cpp index 6ef577362..99d368e37 100644 --- a/src/common/backend/utils/adt/arrayfuncs.cpp +++ b/src/common/backend/utils/adt/arrayfuncs.cpp @@ -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); +} + diff --git a/src/gausskernel/optimizer/plan/planner.cpp b/src/gausskernel/optimizer/plan/planner.cpp index 9c02bb9a0..45ceb0c82 100644 --- a/src/gausskernel/optimizer/plan/planner.cpp +++ b/src/gausskernel/optimizer/plan/planner.cpp @@ -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;