diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index b5f4a020f..5d6412058 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -4239,6 +4239,14 @@ static void transformLockingClause(ParseState* pstate, Query* qry, LockingClause /* make a clause we can pass down to subqueries to select all rels */ allrels = makeNode(LockingClause); allrels->lockedRels = NIL; /* indicates all rels */ + /* The strength of lc is not set at old version and distribution. Set it according to forUpdate. */ + if (t_thrd.proc->workingVersionNum < ENHANCED_TUPLE_LOCK_VERSION_NUM +#ifdef ENABLE_MULTIPLE_NODES + || true +#endif + ) { + lc->strength = lc->forUpdate ? LCS_FORUPDATE : LCS_FORSHARE; + } allrels->strength = lc->strength; allrels->noWait = lc->noWait; @@ -4404,6 +4412,7 @@ void applyLockingClause(Query* qry, Index rtindex, LockClauseStrength strength, * And of course pushedDown becomes false if any clause is explicit. */ rc->strength = Max(rc->strength, strength); + rc->forUpdate = rc->strength == LCS_FORUPDATE; rc->noWait = rc->noWait || noWait; rc->pushedDown = rc->pushedDown && pushedDown; return; @@ -4413,6 +4422,7 @@ void applyLockingClause(Query* qry, Index rtindex, LockClauseStrength strength, rc = makeNode(RowMarkClause); rc->rti = rtindex; rc->strength = strength; + rc->forUpdate = strength == LCS_FORUPDATE; rc->noWait = noWait; rc->pushedDown = pushedDown; qry->rowMarks = lappend(qry->rowMarks, rc); diff --git a/src/common/backend/utils/adt/ri_triggers.cpp b/src/common/backend/utils/adt/ri_triggers.cpp index 59707b5e0..3ca3ce7ad 100644 --- a/src/common/backend/utils/adt/ri_triggers.cpp +++ b/src/common/backend/utils/adt/ri_triggers.cpp @@ -212,6 +212,19 @@ Datum RI_FKey_noaction(PG_FUNCTION_ARGS); template Datum RI_FKey_setdefault(PG_FUNCTION_ARGS); +/* + * Since tuple lock has been enhanced, KeyShareLock is needed instead + * of ShareLock for foreign key. But ustore table still acquires ShareLock. + */ +static inline bool IsShareLockForForeignKey(Relation relation) +{ +#ifdef ENABLE_MULTIPLE_NODES + return true; +#else + return RelationIsUstoreFormat(relation); +#endif +} + /* ---------- * RI_FKey_check - * @@ -321,13 +334,10 @@ static Datum RI_FKey_check(PG_FUNCTION_ARGS) * ---------- */ quoteRelationName(pkrelname, pk_rel); -#ifdef ENABLE_MULTIPLE_NODES - rc = snprintf_s( - querystr, sizeof(querystr), sizeof(querystr) - 1, "SELECT 1 FROM ONLY %s x FOR SHARE OF x", pkrelname); -#else + rc = snprintf_s(querystr, sizeof(querystr), sizeof(querystr) - 1, + IsShareLockForForeignKey(trigdata->tg_relation) ? "SELECT 1 FROM ONLY %s x FOR SHARE OF x" : "SELECT 1 FROM ONLY %s x FOR KEY SHARE OF x", pkrelname); -#endif securec_check_ss(rc, "\0", "\0"); /* Prepare and save the plan */ @@ -465,11 +475,9 @@ static Datum RI_FKey_check(PG_FUNCTION_ARGS) querysep = "AND"; queryoids[i] = fk_type; } -#ifdef ENABLE_MULTIPLE_NODES - appendStringInfo(&querybuf, " FOR SHARE OF x"); -#else - appendStringInfo(&querybuf, " FOR KEY SHARE OF x"); -#endif + + appendStringInfo(&querybuf, IsShareLockForForeignKey(trigdata->tg_relation) ? " FOR SHARE OF x" : + " FOR KEY SHARE OF x"); /* Prepare and save the plan */ qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids, &qkey, fk_rel, pk_rel, true); @@ -617,12 +625,8 @@ static bool ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, HeapTuple old_ro querysep = "AND"; queryoids[i] = pk_type; } -#ifdef ENABLE_MULTIPLE_NODES - appendStringInfo(&querybuf, " FOR SHARE OF x"); -#else - appendStringInfo(&querybuf, " FOR KEY SHARE OF x"); -#endif + appendStringInfo(&querybuf, IsShareLockForForeignKey(pk_rel) ? " FOR SHARE OF x" : " FOR KEY SHARE OF x"); /* Prepare and save the plan */ qplan = ri_PlanCheck(querybuf.data, riinfo->nkeys, queryoids, &qkey, fk_rel, pk_rel, true); @@ -793,11 +797,9 @@ Datum RI_FKey_noaction(PG_FUNCTION_ARGS) querysep = "AND"; queryoids[i] = pk_type; } -#ifdef ENABLE_MULTIPLE_NODES - appendStringInfo(&querybuf, " FOR SHARE OF x"); -#else - appendStringInfo(&querybuf, " FOR KEY SHARE OF x"); -#endif + + appendStringInfo(&querybuf, IsShareLockForForeignKey(trigdata->tg_relation) ? + " FOR SHARE OF x" : " FOR KEY SHARE OF x"); /* Prepare and save the plan */ qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids, &qkey, fk_rel, pk_rel, true); @@ -1332,11 +1334,9 @@ Datum RI_FKey_restrict(PG_FUNCTION_ARGS) querysep = "AND"; queryoids[i] = pk_type; } -#ifdef ENABLE_MULTIPLE_NODES - appendStringInfo(&querybuf, " FOR SHARE OF x"); -#else - appendStringInfo(&querybuf, " FOR KEY SHARE OF x"); -#endif + + appendStringInfo(&querybuf, IsShareLockForForeignKey(trigdata->tg_relation) ? + " FOR SHARE OF x" : " FOR KEY SHARE OF x"); /* Prepare and save the plan */ qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids, &qkey, fk_rel, pk_rel, true); diff --git a/src/gausskernel/optimizer/plan/planner.cpp b/src/gausskernel/optimizer/plan/planner.cpp index 789bf1bce..4efc95fa7 100755 --- a/src/gausskernel/optimizer/plan/planner.cpp +++ b/src/gausskernel/optimizer/plan/planner.cpp @@ -4908,6 +4908,14 @@ static void preprocess_rowmarks(PlannerInfo* root) newrc = makeNode(PlanRowMark); newrc->rti = newrc->prti = rc->rti; newrc->rowmarkId = ++(root->glob->lastRowMarkId); + /* The strength of lc is not set at old version and distribution. Set it according to forUpdate. */ + if (t_thrd.proc->workingVersionNum < ENHANCED_TUPLE_LOCK_VERSION_NUM +#ifdef ENABLE_MULTIPLE_NODES + || true +#endif + ) { + rc->strength = rc->forUpdate ? LCS_FORUPDATE : LCS_FORSHARE; + } switch (rc->strength) { case LCS_FORUPDATE: newrc->markType = ROW_MARK_EXCLUSIVE; diff --git a/src/gausskernel/storage/access/common/reloptions.cpp b/src/gausskernel/storage/access/common/reloptions.cpp index fb49c1f43..0c827561e 100644 --- a/src/gausskernel/storage/access/common/reloptions.cpp +++ b/src/gausskernel/storage/access/common/reloptions.cpp @@ -2911,7 +2911,7 @@ bool is_contain_crossbucket(List *defList) bool is_cstore_option(char relkind, Datum reloptions) { StdRdOptions* std_opt = (StdRdOptions*)heap_reloptions(relkind, reloptions, false); - bool result = std_opt == NULL && pg_strcasecmp(ORIENTATION_COLUMN, + bool result = std_opt != NULL && pg_strcasecmp(ORIENTATION_COLUMN, StdRdOptionsGetStringData(std_opt, orientation, ORIENTATION_ROW)) == 0; pfree_ext(std_opt); return result; diff --git a/src/gausskernel/storage/access/heap/heapam.cpp b/src/gausskernel/storage/access/heap/heapam.cpp index db1da40b1..91faac420 100755 --- a/src/gausskernel/storage/access/heap/heapam.cpp +++ b/src/gausskernel/storage/access/heap/heapam.cpp @@ -5174,8 +5174,14 @@ l2: * If the tuple we're updating is locked, we need to preserve the locking * info in the old tuple's Xmax. Prepare a new Xmax value for this. */ - ComputeNewXmaxInfomask(HeapTupleGetRawXmax(&oldtup), oldtup.t_data->t_infomask, oldtup.t_data->t_infomask2, - xid, mode, true, &xmax_old_tuple, &infomask_old_tuple, &infomask2_old_tuple); + if (t_thrd.proc->workingVersionNum >= ENHANCED_TUPLE_LOCK_VERSION_NUM) { + ComputeNewXmaxInfomask(HeapTupleGetRawXmax(&oldtup), oldtup.t_data->t_infomask, oldtup.t_data->t_infomask2, + xid, mode, true, &xmax_old_tuple, &infomask_old_tuple, &infomask2_old_tuple); + } else { + xmax_old_tuple = xid; + infomask_old_tuple = 0; + infomask2_old_tuple = HEAP_KEYS_UPDATED; + } /* And also prepare an Xmax value for the new copy of the tuple */ if ((oldtup.t_data->t_infomask & HEAP_XMAX_INVALID) || (checked_lockers && !locker_remains)) { @@ -5199,7 +5205,7 @@ l2: if (t_thrd.proc->workingVersionNum < ENHANCED_TUPLE_LOCK_VERSION_NUM) { /* if the only locker of old tuple is ourselves, xmax_new_tuple may be xid and it would be valid */ if (TransactionIdIsValid(xmax_new_tuple) || !TransactionIdEquals(xmax_old_tuple, xid)) { - ereport(WARNING, (errcode(ERRCODE_INVALID_TRANSACTION_STATE), + ereport(DEBUG2, (errcode(ERRCODE_INVALID_TRANSACTION_STATE), errmsg("New MultiXact feature isn't support in this version. Please upgrade to version: %d", ENHANCED_TUPLE_LOCK_VERSION_NUM))); } diff --git a/src/gausskernel/storage/access/table/tableam.cpp b/src/gausskernel/storage/access/table/tableam.cpp index 30a51f8ba..bf54e92a3 100644 --- a/src/gausskernel/storage/access/table/tableam.cpp +++ b/src/gausskernel/storage/access/table/tableam.cpp @@ -1606,6 +1606,10 @@ TM_Result UHeapamTupleUpdate(Relation relation, Relation parentRelation, ItemPoi TM_Result result = UHeapUpdate(relation, parentRelation, otid, (UHeapTuple)newtup, cid, crosscheck, snapshot, wait, oldslot, tmfd, update_indexes, modifiedIdxAttrs, allow_inplace_update); + /* the LockTupleMode of ustore-updating must be LockTupleExclusive now */ + if (mode != NULL) { + *mode = LockTupleExclusive; + } return result; } diff --git a/src/gausskernel/storage/access/transam/multixact.cpp b/src/gausskernel/storage/access/transam/multixact.cpp index 0cf8168df..2a3d12897 100644 --- a/src/gausskernel/storage/access/transam/multixact.cpp +++ b/src/gausskernel/storage/access/transam/multixact.cpp @@ -680,9 +680,8 @@ static MultiXactId CreateMultiXactId(int nmembers, MultiXactMember *members) for (int i = 0; i < nmembers; ++i) { if (members[i].status != MultiXactStatusForShare) { ereport(ERROR, (errcode(ERRCODE_INVALID_TRANSACTION_STATE), - errmsg("New MultiXact feature isn't support in this version. Please upgrade to version: %d" - "i: %d, members[i].status: %d", - ENHANCED_TUPLE_LOCK_VERSION_NUM, i, members[i].status))); + errmsg("New MultiXact feature isn't support in this version. Please upgrade to version: %d", + ENHANCED_TUPLE_LOCK_VERSION_NUM))); } } } diff --git a/src/gausskernel/storage/access/ustore/knl_uheap.cpp b/src/gausskernel/storage/access/ustore/knl_uheap.cpp index 41f52fcf4..05dfd1b02 100644 --- a/src/gausskernel/storage/access/ustore/knl_uheap.cpp +++ b/src/gausskernel/storage/access/ustore/knl_uheap.cpp @@ -1630,6 +1630,10 @@ static void UHeapExecuteLockTuple(Relation relation, Buffer buffer, UHeapTuple u TransactionId xidOnTup = InvalidTransactionId; TransactionId curxid = InvalidTransactionId; + if (mode == LockTupleKeyShare || mode == LockTupleNoKeyExclusive) { + ereport(ERROR, (errmsg("For Key Share and For No Key Update is not support for ustore."))); + } + if (mode == LockTupleExclusive) { xid = GetCurrentTransactionId(); } else if (mode == LockTupleShared) {