From eeb50f6c672006fb75600bb57794d96999001e70 Mon Sep 17 00:00:00 2001 From: laishenghao Date: Mon, 17 Apr 2023 11:37:26 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3MySQL=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=B8=8B=20insert=20on=20duplicate=20key=E8=AF=AD=E6=B3=95?= =?UTF-8?q?=E5=AE=95=E6=9C=BA=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/parser/analyze.cpp | 19 +++++++++++++++---- .../runtime/executor/execUtils.cpp | 17 +++++++++++++++-- src/include/nodes/parsenodes_common.h | 2 +- .../regress/input/insert_right_ref.source | 12 ++++++++++++ .../regress/output/insert_right_ref.source | 12 ++++++++++++ 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 82ba626a7..d8087112e 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -1614,17 +1614,23 @@ static void SetUpsertAttrnoState(ParseState* pstate, List *targetList) return; } RightRefState* rstate = pstate->rightRefState; - int len = list_length(targetList); + const int len = list_length(targetList); rstate->usExplicitAttrLen = len; rstate->usExplicitAttrNos = (int*)palloc0(sizeof(int) * len); Relation relation = (Relation)linitial(pstate->p_target_relation); FormData_pg_attribute* attr = relation->rd_att->attrs; - int colNum = RelationGetNumberOfAttributes(relation); + const int colNum = RelationGetNumberOfAttributes(relation); ListCell* target = list_head(targetList); for (int ni = 0; ni < len; ++ni) { ResTarget* res = (ResTarget*)lfirst(target); - const char* name = res->name; + char* name = nullptr; + if (list_length(res->indirection) > 0) { + name = ((Value*)llast(res->indirection))->val.str; + } else { + name = res->name; + } + for (int ci = 0; ci < colNum; ++ci) { if (attr[ci].attisdropped) { continue; @@ -1634,7 +1640,12 @@ static void SetUpsertAttrnoState(ParseState* pstate, List *targetList) break; } } - + + if (rstate->usExplicitAttrNos[ni] == InvalidOid) { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("Column \"%s\" not found in upsert attrno state initialization", name))); + } target = lnext(target); } } diff --git a/src/gausskernel/runtime/executor/execUtils.cpp b/src/gausskernel/runtime/executor/execUtils.cpp index 3a87a22fc..77989d9d3 100644 --- a/src/gausskernel/runtime/executor/execUtils.cpp +++ b/src/gausskernel/runtime/executor/execUtils.cpp @@ -2870,7 +2870,13 @@ void SortTargetListAsArray(RightRefState* refState, List* targetList, GenericExp } } - Assert(defaultNodeOffset == len); + if (defaultNodeOffset != len) { + /* this should never happen, the system must come in mess */ + ereport(ERROR, + (errcode(ERRCODE_INVALID_STATUS), + errmsg("the number of elements put up does not match the length of targetlist, array:%d, list:%d", + defaultNodeOffset, len))); + } } else if (IS_ENABLE_UPSERT_RIGHT_REF(refState)) { const int len = list_length(targetList); GenericExprState* tempArr[len]; @@ -2891,7 +2897,14 @@ void SortTargetListAsArray(RightRefState* refState, List* targetList, GenericExp targetArr[defaultNodeOffset++] = tempArr[i]; } } - Assert(defaultNodeOffset == len); + + if (defaultNodeOffset != len) { + /* this should never happen, the system must come in mess */ + ereport(ERROR, + (errcode(ERRCODE_INVALID_STATUS), + errmsg("the number of elements put up does not match the length of targetlist, array:%d, list:%d", + defaultNodeOffset, len))); + } } else { int index = 0; foreach(lc, targetList) { diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index 49ff2c704..043c660ea 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -405,7 +405,7 @@ typedef struct A_Indices { */ typedef struct ResTarget { NodeTag type; - char *name; /* column name or NULL */ + char *name; /* column name or NULL or first part of name(db, schema or table name) of destination column */ List *indirection; /* subscripts, field names, and '*', or NIL */ Node *val; /* the value expression to compute or assign */ int location; /* token location, or -1 if unknown */ diff --git a/src/test/regress/input/insert_right_ref.source b/src/test/regress/input/insert_right_ref.source index 2a1d5cf5a..da39b5356 100644 --- a/src/test/regress/input/insert_right_ref.source +++ b/src/test/regress/input/insert_right_ref.source @@ -438,6 +438,18 @@ VALUES 't_log_replica_mysql_2' ) RETURNING i_id_batch; +-- upsert case +CREATE TABLE t2 ( + col1 INT, + col2 INT PRIMARY KEY, + col3 INT DEFAULT 1, + col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + col5 BIGSERIAL +); + +INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = t2.col2 + 1; +INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4); + -- jdbc case DROP USER IF EXISTS rightref CASCADE; CREATE USER rightref WITH PASSWORD 'rightref@123'; diff --git a/src/test/regress/output/insert_right_ref.source b/src/test/regress/output/insert_right_ref.source index 5f10a59ca..4e05f4ee5 100644 --- a/src/test/regress/output/insert_right_ref.source +++ b/src/test/regress/output/insert_right_ref.source @@ -613,6 +613,18 @@ VALUES 3 (1 row) +-- upsert case +CREATE TABLE t2 ( + col1 INT, + col2 INT PRIMARY KEY, + col3 INT DEFAULT 1, + col4 TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + col5 BIGSERIAL +); +NOTICE: CREATE TABLE will create implicit sequence "t2_col5_seq" for serial column "t2.col5" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2" +INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = t2.col2 + 1; +INSERT INTO t2 VALUES (6, 6) ON DUPLICATE KEY UPDATE t2.col1 = extract(century from col4) * 100 + extract(isodow from col4); -- jdbc case DROP USER IF EXISTS rightref CASCADE; NOTICE: role "rightref" does not exist, skipping