!3342 【bugfixed】解决MySQL模式下 insert on duplicate key语法宕机的问题
Merge pull request !3342 from laishenghao/upsert-core
This commit is contained in:
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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';
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user