!3342 【bugfixed】解决MySQL模式下 insert on duplicate key语法宕机的问题

Merge pull request !3342 from laishenghao/upsert-core
This commit is contained in:
opengauss-bot
2023-04-17 10:57:15 +00:00
committed by Gitee
5 changed files with 55 additions and 7 deletions

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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 */

View File

@ -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';

View File

@ -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