!1448 修复upsert子查询、first last函数等特性功能不可用问题

Merge pull request !1448 from gentle_hu/guass
This commit is contained in:
opengauss-bot 2022-01-05 01:36:31 +00:00 committed by Gitee
commit 6057d21b37
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
24 changed files with 412 additions and 64 deletions

View File

@ -258,6 +258,7 @@ hot_standby_feedback|bool|0,0|NULL|NULL|
ident_file|string|0,0|NULL|NULL|
ignore_checksum_failure|bool|0,0|NULL|Continues processing after a checksum failure.|
ignore_system_indexes|bool|0,0|NULL|When ignore_system_indexes set to on, it is very useful for recovering data from the table which system index is corrupted.|
parctl_min_cost|int|-1,2147483647|NULL|NULL|
io_control_unit|int|1000,1000000|NULL|NULL|
gin_pending_list_limit|int|64,2147483647|kB|NULL|
intervalstyle|enum|postgres,postgres_verbose,sql_standard,iso_8601,a|NULL|NULL|

View File

@ -352,6 +352,14 @@
"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("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
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_replace", 1,
AddBuiltinFunc(_0(6556), _1("array_replace"), _2(3), _3(false), _4(false), _5(array_replace), _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(3, 2277, 2283,2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("array_replace"), _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("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
@ -2550,6 +2558,14 @@
"fenced_udf_process", 1,
AddBuiltinFunc(_0(4207), _1("fenced_udf_process"), _2(1), _3(true), _4(false), _5(fenced_udf_process), _6(25), _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, 23), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("fenced_udf_process"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"first", 1,
AddBuiltinFunc(_0(6560), _1("first"), _2(1), _3(false), _4(false), _5(aggregate_dummy), _6(2283), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(true), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("aggregate_dummy"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))
),
AddFuncGroup(
"first_transition", 1,
AddBuiltinFunc(_0(6558), _1("first_transition"), _2(2), _3(true), _4(false), _5(first_transition), _6(2283), _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, 2283, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("first_transition"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))
),
AddFuncGroup(
"finish", 1,
AddBuiltinFunc(_0(1518), _1("finish"), _2(0), _3(true), _4(true), _5(debug_client_finish), _6(2249), _7(PG_PLDEBUG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(1), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(4, 26, 25, 23, 25), _22(4, 'o', 'o', 'o', 'o'), _23(4, "funcoid", "funcname", "lineno", "query"), _24(NULL), _25("debug_client_finish"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(false), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
@ -6025,10 +6041,18 @@
"language_handler_out", 1,
AddBuiltinFunc(_0(2303), _1("language_handler_out"), _2(1), _3(true), _4(false), _5(language_handler_out), _6(2275), _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(1, 2280), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("language_handler_out"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("I/O"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"last", 1,
AddBuiltinFunc(_0(6561), _1("last"), _2(1), _3(false), _4(false), _5(aggregate_dummy), _6(2283), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(true), _15(false), _16(false), _17(false), _18('i'), _19(0), _20(1, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("aggregate_dummy"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))
),
AddFuncGroup(
"last_day", 1,
AddBuiltinFunc(_0(4075), _1("last_day"), _2(1), _3(true), _4(false), _5(last_day), _6(1114), _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(1, 1114), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("last_day"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"last_transition", 1,
AddBuiltinFunc(_0(6559), _1("last_transition"), _2(2), _3(true), _4(false), _5(last_transition), _6(2283), _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, 2283, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("last_transition"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33(NULL), _34('f'))
),
AddFuncGroup(
"last_value", 1,
AddBuiltinFunc(_0(3113), _1("last_value"), _2(1), _3(true), _4(false), _5(window_last_value), _6(2283), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(0), _12(0), _13(0), _14(false), _15(true), _16(false), _17(false), _18('i'), _19(0), _20(1, 2283), _21(NULL), _22(NULL), _23(NULL), _24(NULL), _25("window_last_value"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("fetch the last row value"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))

View File

@ -17959,6 +17959,7 @@ upsert_clause:
n->targetList = $5;
$$ = (Node *) n;
} else {
#ifdef ENABLE_MULTIPLE_NODES
/* check subquery in set clause*/
ListCell* cell = NULL;
ResTarget* res = NULL;
@ -17966,14 +17967,14 @@ upsert_clause:
res = (ResTarget*)lfirst(cell);
if (IsA(res->val,SubLink)) {
const char* message = "Update with subquery is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.";
InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc);
InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc);
ereport(errstate,
(errmodule(MOD_PARSER),
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("Update with subquery is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.")));
}
}
#endif
UpsertClause *uc = makeNode(UpsertClause);
uc->targetList = $5;
uc->location = @1;

View File

@ -39,7 +39,7 @@ OBJS = acl.o arrayfuncs.o array_selfuncs.o array_typanalyze.o \
tsquery_op.o tsquery_rewrite.o tsquery_util.o tsrank.o \
tsvector.o tsvector_op.o tsvector_parser.o \
txid.o uuid.o windowfuncs.o xml.o extended_statistics.o clientlogic_bytea.o clientlogicsettings.o \
median_aggs.o expr_distinct.o nlssort.o
median_aggs.o expr_distinct.o nlssort.o first_last_agg.o
like.o: like.cpp like_match.cpp

View File

@ -5531,6 +5531,279 @@ Datum array_unnest(PG_FUNCTION_ARGS)
}
}
/*
* check if search is same as replace
*/
static bool array_same_replace(FunctionCallInfo locfcinfo, Datum search, bool search_isnull,
Datum replace, bool replace_isnull)
{
if (search_isnull != replace_isnull) {
return false;
} else if (search_isnull == true) {
Assert(replace_isnull);
return true;
} else {
locfcinfo->arg[0] = search;
locfcinfo->arg[1] = replace;
locfcinfo->argnull[0] = search_isnull;
locfcinfo->argnull[1] = replace_isnull;
locfcinfo->isnull = false;
return DatumGetBool(FunctionCallInvoke(locfcinfo));
}
}
/*
* 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 = NULL;
Oid element_type;
Datum *values = NULL;
bool *nulls = NULL;
int *dim = NULL;
int ndim;
int nitems;
int nresult;
int i;
int32 nbytes = 0;
int32 dataoffset;
bool hasnulls = false;
int typlen;
bool typbyval = false;
char typalign;
char *arraydataptr = NULL;
bits8 *bitmap = NULL;
int bitmask;
bool changed = false;
TypeCacheEntry *typentry = NULL;
FunctionCallInfoData locfcinfo;
errno_t rc = EOK;
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);
/* directly return if search is same as replace */
if (!remove && array_same_replace(&locfcinfo, search, search_isnull, replace, replace_isnull)) {
return array;
}
/* 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 = false;
bool oprresult = false;
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;
rc = memcpy_s(ARR_DIMS(result), nbytes - sizeof(ArrayType), ARR_DIMS(array), ndim * sizeof(int));
securec_check(rc, "\0", "\0");
rc = memcpy_s(ARR_LBOUND(result), nbytes - (sizeof(ArrayType) + sizeof(int) * ndim),
ARR_LBOUND(array), ndim * sizeof(int));
securec_check(rc, "\0", "\0");
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 = NULL;
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 = NULL;
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);
}
/*
* The type, dimension needs to be checked during collection operations.
*/

View File

@ -32,4 +32,4 @@ Datum first_transition(PG_FUNCTION_ARGS)
Datum last_transition(PG_FUNCTION_ARGS)
{
PG_RETURN_DATUM(PG_GETARG_DATUM(1));
}
}

View File

@ -4601,10 +4601,12 @@ static void set_deparse_planstate(deparse_namespace* dpns, PlanState* ps)
#ifdef ENABLE_MULTIPLE_NODES
if (IsA(ps, ModifyTableState))
dpns->inner_tlist = ((ModifyTableState*)ps)->mt_upsert->us_excludedtlist;
else
#else
if (IsA(ps, ModifyTableState) && ((ModifyTableState*)ps)->mt_upsert != NULL &&
((ModifyTableState*)ps)->mt_upsert->us_action != UPSERT_NONE)
#endif
if (dpns->inner_planstate != NULL)
dpns->inner_tlist = ((ModifyTableState*)ps)->mt_upsert->us_excludedtlist;
else if (dpns->inner_planstate != NULL)
dpns->inner_tlist = dpns->inner_planstate->plan->targetlist;
else
dpns->inner_tlist = NIL;

View File

@ -1006,7 +1006,7 @@ static bool check_cgroup_name(char** newval, void** extra, GucSource source)
p = *newval;
if (StringIsValid(p) && IS_PGXC_COORDINATOR && t_thrd.shemem_ptr_cxt.MyBEEntry &&
if (StringIsValid(p) && IS_SERVICE_NODE && t_thrd.shemem_ptr_cxt.MyBEEntry &&
(currentGucContext == PGC_SUSET || currentGucContext == PGC_USERSET)) {
if (g_instance.wlm_cxt->gscgroup_init_done == 0)
ereport(ERROR,
@ -1035,7 +1035,7 @@ static bool check_cgroup_name(char** newval, void** extra, GucSource source)
static void assign_cgroup_name(const char* newval, void* extra)
{
/* set "control_group" global variable */
if (IS_PGXC_COORDINATOR && t_thrd.shemem_ptr_cxt.MyBEEntry && newval && *newval) {
if (IS_SERVICE_NODE && t_thrd.shemem_ptr_cxt.MyBEEntry && newval && *newval) {
if (g_instance.wlm_cxt->gscgroup_init_done == 0)
return;

View File

@ -1796,7 +1796,7 @@ bool WLMIsSimpleQuery(const QueryDesc* queryDesc, bool force_control, bool isQue
g_wlm_params->use_planA = false;
if (IS_PGXC_DATANODE || (IS_PGXC_COORDINATOR && IsConnFromCoord()) ||
if (COORDINATOR_NOT_SINGLE || (IS_SERVICE_NODE && IsConnFromCoord()) ||
u_sess->attr.attr_resource.parctl_min_cost < 0) {
return true;
}
@ -1875,7 +1875,7 @@ bool WLMIsSimpleQuery(const QueryDesc* queryDesc, bool force_control, bool isQue
*/
bool WLMNeedTrackResource(const QueryDesc* queryDesc)
{
if ((!(IS_SINGLE_NODE || IS_PGXC_COORDINATOR)) || (IS_PGXC_COORDINATOR && IsConnFromCoord()) ||
if (!IS_SERVICE_NODE || (IS_PGXC_COORDINATOR && IsConnFromCoord()) ||
t_thrd.wlm_cxt.collect_info->sdetail.statement == NULL || !u_sess->attr.attr_resource.enable_resource_track ||
u_sess->attr.attr_resource.resource_track_cost < 0 || u_sess->attr.attr_sql.enable_cluster_resize ||
t_thrd.wlm_cxt.parctl_state.special) {
@ -2929,7 +2929,7 @@ void WLMSwitchCGroup(void)
}
/* simple query will skip the cgroup loading */
if (IS_PGXC_COORDINATOR && (IsConnFromCoord() || t_thrd.wlm_cxt.parctl_state.simple)) {
if (IS_SERVICE_NODE && (IsConnFromCoord() || t_thrd.wlm_cxt.parctl_state.simple)) {
return;
}

View File

@ -160,6 +160,12 @@ List* check_op_list_template(Plan* result_plan, List* (*check_eval)(Node*))
res_list = list_concat_unique(res_list, check_eval((Node*)splan->resconstantqual));
} break;
case T_ModifyTable: {
ModifyTable* splan = (ModifyTable*)result_plan;
if (splan->upsertAction == UPSERT_UPDATE && splan->updateTlist != NULL) {
res_list = list_concat_unique(res_list, check_eval((Node*)splan->updateTlist));
}
} break;
default:
break;
}

View File

@ -6389,9 +6389,6 @@ void standard_ProcessUtility(Node* parse_tree, const char* query_string, ParamLi
break;
case T_CreateResourcePoolStmt:
#ifndef ENABLE_MULTIPLE_NODES
DISTRIBUTED_FEATURE_NOT_SUPPORTED();
#endif
if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) {
char* first_exec_node = find_first_exec_cn();
bool is_first_node = (strcmp(first_exec_node, g_instance.attr.attr_common.PGXCNodeName) == 0);
@ -6448,9 +6445,6 @@ void standard_ProcessUtility(Node* parse_tree, const char* query_string, ParamLi
break;
case T_AlterResourcePoolStmt:
#ifndef ENABLE_MULTIPLE_NODES
DISTRIBUTED_FEATURE_NOT_SUPPORTED();
#endif
if (IS_PGXC_COORDINATOR) {
char* first_exec_node = find_first_exec_cn();
bool is_first_node = (strcmp(first_exec_node, g_instance.attr.attr_common.PGXCNodeName) == 0);
@ -6471,9 +6465,6 @@ void standard_ProcessUtility(Node* parse_tree, const char* query_string, ParamLi
break;
case T_DropResourcePoolStmt:
#ifndef ENABLE_MULTIPLE_NODES
DISTRIBUTED_FEATURE_NOT_SUPPORTED();
#endif
if (IS_PGXC_COORDINATOR) {
char* first_exec_node = find_first_exec_cn();
bool is_first_node = (strcmp(first_exec_node, g_instance.attr.attr_common.PGXCNodeName) == 0);

View File

@ -1565,6 +1565,10 @@ bool ExecCheckIndexConstraints(TupleTableSlot *slot, EState *estate, Relation ta
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("INSERT ON DUPLICATE KEY UPDATE does not support deferrable"
" unique constraints/exclusion constraints.")));
/*
* We consider a partitioned table with a global index as a normal table,
* because conflicts can be between multiple partitions.
*/
if (isPartitioned && !isgpi) {
partitionedindexid = RelationGetRelid(indexRelation);

View File

@ -338,6 +338,10 @@ DATA(insert ( 3545 bytea_string_agg_transfn - bytea_string_agg_finalfn 0 2281 _
DATA(insert ( 3124 json_agg_transfn - json_agg_finalfn 0 2281 _null_ _null_ n 0));
DATA(insert ( 3403 json_object_agg_transfn - json_object_agg_finalfn 0 2281 _null_ _null_ n 0));
/* first last */
DATA(insert ( 6560 first_transition - - 0 2283 _null_ _null_ n 0));
DATA(insert ( 6561 last_transition - - 0 2283 _null_ _null_ n 0));
/* hll distribute agg */
DATA(insert ( 4366 hll_add_trans0 hll_union_collect hll_pack 0 4370 _null_ _null_ n 0));
#define HLL_ADD_TRANS0_OID 4366

View File

@ -45,6 +45,7 @@ typedef enum {
#define IS_SINGLE_NODE (g_instance.role == VSINGLENODE)
#define REMOTE_CONN_TYPE u_sess->attr.attr_common.remoteConnType
#define COORDINATOR_NOT_SINGLE (g_instance.role == VDATANODE && g_instance.role != VSINGLENODE)
#define IS_SERVICE_NODE (g_instance.role == VCOORDINATOR || g_instance.role == VSINGLENODE)
#define IsConnFromApp() (u_sess->attr.attr_common.remoteConnType == REMOTE_CONN_APP)
#define IsConnFromCoord() (u_sess->attr.attr_common.remoteConnType == REMOTE_CONN_COORD)

View File

@ -1,10 +1,10 @@
select oid, * from pg_proc where proname in ('first', 'first_transition', 'last', 'last_transition') order by oid;
oid | proname | pronamespace | proowner | prolang | procost | prorows | provariadic | protransform | proisagg | proiswindow | prosecdef | proleakproof | proisstrict | proretset | provolatile | pronargs | pronargdefaults | prorettype | proargtypes | proallargtypes | proargmodes | proargnames | proargdefaults | prosrc | probin | proconfig | proacl | prodefaultargpos | fencedmode | proshippable | propackage | prokind | proargsrc | propackageid | proisprivate | proargtypesext | prodefaultargposext
------+------------------+--------------+----------+---------+---------+---------+-------------+--------------+----------+-------------+-----------+--------------+-------------+-----------+-------------+----------+-----------------+------------+-------------+----------------+-------------+-------------+----------------+------------------+--------+-----------+--------+------------------+------------+--------------+------------+---------+-----------+--------------+--------------+----------------+---------------------
6558 | first_transition | 11 | 10 | 12 | 1 | 0 | 0 | - | f | f | f | f | t | f | i | 2 | 0 | 2283 | 2283 2283 | | | | | first_transition | | | | | f | | f | f | | 0 | f | |
6559 | last_transition | 11 | 10 | 12 | 1 | 0 | 0 | - | f | f | f | f | t | f | i | 2 | 0 | 2283 | 2283 2283 | | | | | last_transition | | | | | f | | f | f | | 0 | f | |
6560 | first | 11 | 10 | 12 | 1 | 0 | 0 | - | t | f | f | f | f | f | i | 1 | 0 | 2283 | 2283 | | | | | aggregate_dummy | | | | | f | | f | f | | 0 | f | |
6561 | last | 11 | 10 | 12 | 1 | 0 | 0 | - | t | f | f | f | f | f | i | 1 | 0 | 2283 | 2283 | | | | | aggregate_dummy | | | | | f | | f | f | | 0 | f | |
oid | proname | pronamespace | proowner | prolang | procost | prorows | provariadic | protransform | proisagg | proiswindow | prosecdef | proleakproof | proisstrict | proretset | provolatile | pronargs | pronargdefaults | prorettype | proargtypes | proallargtypes | proargmodes | proargnames | proargdefaults | prosrc | probin | proconfig | proacl | prodefaultargpos | fencedmode | proshippable | propackage | prokind | proargsrc | propackageid | proisprivate | proargtypesext | prodefaultargposext | allargtypes | allargtypesext
------+------------------+--------------+----------+---------+---------+---------+-------------+--------------+----------+-------------+-----------+--------------+-------------+-----------+-------------+----------+-----------------+------------+-------------+----------------+-------------+-------------+----------------+------------------+--------+-----------+--------+------------------+------------+--------------+------------+---------+-----------+--------------+--------------+----------------+---------------------+-------------+----------------
6558 | first_transition | 11 | 10 | 12 | 1 | 0 | 0 | - | f | f | f | f | t | f | i | 2 | 0 | 2283 | 2283 2283 | | | | | first_transition | | | | | f | | f | f | | 0 | f | | | 2283 2283 |
6559 | last_transition | 11 | 10 | 12 | 1 | 0 | 0 | - | f | f | f | f | t | f | i | 2 | 0 | 2283 | 2283 2283 | | | | | last_transition | | | | | f | | f | f | | 0 | f | | | 2283 2283 |
6560 | first | 11 | 10 | 12 | 1 | 0 | 0 | - | t | f | f | f | f | f | i | 1 | 0 | 2283 | 2283 | | | | | aggregate_dummy | | | | | f | | f | f | | 0 | f | | | 2283 |
6561 | last | 11 | 10 | 12 | 1 | 0 | 0 | - | t | f | f | f | f | f | i | 1 | 0 | 2283 | 2283 | | | | | aggregate_dummy | | | | | f | | f | f | | 0 | f | | | 2283 |
(4 rows)
create table first_last_test(a int, b int, c int, d int);

View File

@ -51,6 +51,27 @@ INSERT INTO newproducts_row SELECT * FROM newproducts_base;
ANALYZE products_row;
ANALYZE newproducts_row;
-- explain verbose
EXPLAIN (VERBOSE on, COSTS off)
MERGE INTO products_row p
USING newproducts_row np
ON p.product_id = np.product_id
WHEN MATCHED THEN
UPDATE SET product_name = np.product_name, category = np.category, total = np.total where np.product_id = 5;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Merge on mergeinto_1.products_row p
Update Cond: (p.product_id = 5)
-> Hash Join
Output: np.product_id, np.product_name, np.category, np.total, p.product_id, p.product_name, p.category, p.total, p.ctid, np.ctid
Hash Cond: (p.product_id = np.product_id)
-> Seq Scan on mergeinto_1.products_row p
Output: p.product_id, p.product_name, p.category, p.total, p.ctid
-> Hash
Output: np.product_id, np.product_name, np.category, np.total, np.ctid
-> Seq Scan on mergeinto_1.newproducts_row np
Output: np.product_id, np.product_name, np.category, np.total, np.ctid
(11 rows)
EXPLAIN (VERBOSE on, COSTS off)
MERGE INTO products_row p
USING newproducts_row np
@ -59,26 +80,19 @@ WHEN MATCHED THEN
UPDATE SET product_name = np.product_name, category = np.category, total = np.total
WHEN NOT MATCHED THEN
INSERT VALUES (np.product_id, np.product_name, np.category, np.total);
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Streaming (type: GATHER)
Node/s: All datanodes
-> Merge on mergeinto_1.products_row p
-> Streaming(type: REDISTRIBUTE)
Output: np.product_id, np.product_name, np.category, np.total, p.product_id, p.product_name, p.category, p.total, p.ctid, p.xc_node_id, np.ctid, (CASE WHEN (p.ctid IS NULL) THEN np.product_id ELSE p.product_id END)
Distribute Key: (CASE WHEN (p.ctid IS NULL) THEN np.product_id ELSE p.product_id END)
Spawn on: All datanodes
Consumer Nodes: All datanodes
-> Nested Loop Left Join
Output: np.product_id, np.product_name, np.category, np.total, p.product_id, p.product_name, p.category, p.total, p.ctid, p.xc_node_id, np.ctid, CASE WHEN (p.ctid IS NULL) THEN np.product_id ELSE p.product_id END
Join Filter: (p.product_id = np.product_id)
-> Seq Scan on mergeinto_1.newproducts_row np
Output: np.product_id, np.product_name, np.category, np.total, np.ctid
Distribute Key: np.product_id
-> Seq Scan on mergeinto_1.products_row p
Output: p.product_id, p.product_name, p.category, p.total, p.ctid, p.xc_node_id
Distribute Key: p.product_id
(17 rows)
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------
Merge on mergeinto_1.products_row p
-> Hash Right Join
Output: np.product_id, np.product_name, np.category, np.total, p.product_id, p.product_name, p.category, p.total, p.ctid, np.ctid
Hash Cond: (p.product_id = np.product_id)
-> Seq Scan on mergeinto_1.products_row p
Output: p.product_id, p.product_name, p.category, p.total, p.ctid
-> Hash
Output: np.product_id, np.product_name, np.category, np.total, np.ctid
-> Seq Scan on mergeinto_1.newproducts_row np
Output: np.product_id, np.product_name, np.category, np.total, np.ctid
(10 rows)
-- only MATCHED clause
MERGE INTO products_row p

View File

@ -1456,6 +1456,12 @@ WHERE d.classoid IS NULL AND p1.oid <= 9999 order by 1;
6422 | numeric
6433 | numeric
6434 | numeric_bool
6555 | array_remove
6556 | array_replace
6558 | first_transition
6559 | last_transition
6560 | first
6561 | last
6666 | network_larger
6667 | network_smaller
6668 | max

View File

@ -74,6 +74,8 @@ create table pkt (a int primary key, b int, c int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pkt_pkey" for table "pkt"
create table fkt (a int primary key, b int references pkt, c int);
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "fkt_pkey" for table "fkt"
create table up_neg_11(c1 int, c2 int) partition by range(c1)(partition p1 values less than(10), partition p2 values less than(maxvalue));
create unique index index_up_neg_11 on up_neg_11(c2);
-- procedure test
CREATE SCHEMA upsert_test_procedure;
-- explain test

View File

@ -32,6 +32,7 @@ insert into up_neg_07 select a,a,a from generate_series(1,20) as a;
insert into up_neg_08 select a,a,a from generate_series(1,20) as a;
insert into up_neg_09 select a,a,a from generate_series(1,20) as a;
insert into up_neg_10 select a,a,a from generate_series(1,20) as a;
insert into up_neg_11 values(1,1),(2,2),(11,11),(12,12);
-- table cases
---- col table
insert into up_neg_01 values(1,2,3) on duplicate key update c3 = 1;
@ -103,12 +104,6 @@ insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 from up_n
ERROR: syntax error at or near "from"
LINE 1: ... values(1,1,1,1,1) on duplicate key update c4 = 1 from up_ne...
^
---- sub query
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update (c2) = (select c2 from up_neg_05);
ERROR: Update with subquery is not yet supported whithin INSERT ON DUPLICATE KEY UPDATE statement.
---- update distribute key
insert into up_neg_06 values(101, 1, 1) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
---- update partition key
insert into up_neg_07 values(101, 1, 300) on duplicate key update c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
@ -120,6 +115,22 @@ insert into up_neg_09 values(101, 1, 1) on duplicate key update c2=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2 =1,c3=101;
ERROR: INSERT ON DUPLICATE KEY UPDATE don't allow update on primary key or unique key.
---- cross-partition upsert
insert into up_neg_11 values(1, 1) on duplicate key update c1 = 15;
select * from up_neg_11 partition(p1);
c1 | c2
----+----
2 | 2
(1 row)
select * from up_neg_11 partition(p2);
c1 | c2
----+----
11 | 11
12 | 12
15 | 1
(3 rows)
--update unique key mul type plans
EXPLAIN (VERBOSE on, COSTS off) insert into up_neg_10 values(101, 1, 300) on duplicate key update c1=101;
QUERY PLAN

View File

@ -14,7 +14,7 @@ test: analyze_commands
test: single_node_ddl
test: single_node_sqlbypass
#test: mediavarchar.cppn
#test: array_funcs first_last_agg
test: array_funcs first_last_agg
test: get_instr_unique_sql
# run tablespace by itself, and first, because it forces a checkpoint;
@ -165,8 +165,7 @@ test: single_node_sequence
# run and check forbidden functions are still forbidden to use in single node
test: single_node_forbidden
test: single_node_mergeinto
#test: merge_1
test: single_node_mergeinto merge_1
# Trigger tests
test: single_node_triggers
@ -332,7 +331,7 @@ test: upsert_001 upsert_002 upsert_003 upsert_008 upsert_009 upsert_010
test: upsert_grammer_test_01 upsert_unlog_test upsert_tmp_test
test: upsert_grammer_test_02 upsert_restriction upsert_composite
test: upsert_trigger_test upsert_explain
#test: upsert_subquery
test: upsert_subquery
test: upsert_clean
# all pass

View File

@ -5158,7 +5158,7 @@ static void check_global_variables()
}
}
#define BASE_PGXC_LIKE_MACRO_NUM 1416
#define BASE_PGXC_LIKE_MACRO_NUM 1415
static void check_pgxc_like_macros()
{
#ifdef BUILD_BY_CMAKE

View File

@ -64,6 +64,13 @@ ANALYZE products_row;
ANALYZE newproducts_row;
-- explain verbose
EXPLAIN (VERBOSE on, COSTS off)
MERGE INTO products_row p
USING newproducts_row np
ON p.product_id = np.product_id
WHEN MATCHED THEN
UPDATE SET product_name = np.product_name, category = np.category, total = np.total where np.product_id = 5;
EXPLAIN (VERBOSE on, COSTS off)
MERGE INTO products_row p
USING newproducts_row np

View File

@ -59,7 +59,8 @@ create view up_view as select *from up_neg_01;
create materialized view mat_view as select *from up_neg_01;
create table pkt (a int primary key, b int, c int);
create table fkt (a int primary key, b int references pkt, c int);
create table up_neg_11(c1 int, c2 int) partition by range(c1)(partition p1 values less than(10), partition p2 values less than(maxvalue));
create unique index index_up_neg_11 on up_neg_11(c2);
-- procedure test
CREATE SCHEMA upsert_test_procedure;

View File

@ -33,6 +33,7 @@ insert into up_neg_07 select a,a,a from generate_series(1,20) as a;
insert into up_neg_08 select a,a,a from generate_series(1,20) as a;
insert into up_neg_09 select a,a,a from generate_series(1,20) as a;
insert into up_neg_10 select a,a,a from generate_series(1,20) as a;
insert into up_neg_11 values(1,1),(2,2),(11,11),(12,12);
-- table cases
---- col table
@ -86,11 +87,6 @@ insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c1 =1, c2 = 1, c
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 where c1=1;
---- from clause
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update c4 = 1 from up_neg_04 where c1=1;
---- sub query
insert into up_neg_05 values(1,1,1,1,1) on duplicate key update (c2) = (select c2 from up_neg_05);
---- update distribute key
insert into up_neg_06 values(101, 1, 1) on duplicate key update c3=101;
---- update partition key
insert into up_neg_07 values(101, 1, 300) on duplicate key update c3=101;
insert into up_neg_08 values(101, 1, 300) on duplicate key update c3=101;
@ -98,6 +94,11 @@ insert into up_neg_09 values(101, 1, 1) on duplicate key update c3=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2=101;
insert into up_neg_09 values(101, 1, 1) on duplicate key update c2 =1,c3=101;
---- cross-partition upsert
insert into up_neg_11 values(1, 1) on duplicate key update c1 = 15;
select * from up_neg_11 partition(p1);
select * from up_neg_11 partition(p2);
--update unique key mul type plans
EXPLAIN (VERBOSE on, COSTS off) insert into up_neg_10 values(101, 1, 300) on duplicate key update c1=101;
insert into up_neg_10 values(101, 1, 300) on duplicate key update c3=101;