diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index 7b6331a7b..48b3399e0 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -2800,6 +2800,7 @@ modify_column_cmd: $$ = (Node *)n; } | ColId Typename ON_UPDATE_TIME UPDATE b_expr +#ifndef ENBALE_MULTI_NODE { if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { @@ -2828,6 +2829,7 @@ modify_column_cmd: $$ = NULL; } } +#endif | ColId NOT NULL_P opt_enable { AlterTableCmd *n = makeNode(AlterTableCmd); @@ -6328,6 +6330,7 @@ ColConstraintElem: $$ = (Node *)n; } | ON_UPDATE_TIME UPDATE b_expr +#ifndef ENBALE_MULTI_NODE { if (u_sess->attr.attr_sql.sql_compatibility == B_FORMAT) { @@ -6348,6 +6351,7 @@ ColConstraintElem: $$ = NULL; } } +#endif | GENERATED ALWAYS AS '(' a_expr ')' STORED { #ifdef ENABLE_MULTIPLE_NODES diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index f4cf8fea2..7cae52575 100644 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -10015,6 +10015,35 @@ static void ATExecSetNotNull(AlteredTableInfo* tab, Relation rel, const char* co heap_close(attr_rel, RowExclusiveLock); } +bool FetchOnUpdateExpress(Relation rel, char* colName) +{ + HeapTuple htup = NULL; + bool isnull = false; + bool temp_on_update = FALSE; + htup = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); + if (!HeapTupleIsValid(htup)) + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", colName, RelationGetRelationName(rel)))); + Form_pg_attribute attTup = (Form_pg_attribute)GETSTRUCT(htup); + AttrNumber temp_attnum = attTup->attnum; + + ScanKeyData skey[2]; + Relation adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock); + ScanKeyInit(&skey[0], Anum_pg_attrdef_adrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel))); + ScanKeyInit(&skey[1], Anum_pg_attrdef_adnum, BTEqualStrategyNumber, F_INT2EQ, Int16GetDatum(temp_attnum)); + SysScanDesc adscan = systable_beginscan(adrel, AttrDefaultIndexId, true, NULL, 2, skey); + + if (HeapTupleIsValid(htup = systable_getnext(adscan))) { + Datum val = heap_getattr(htup, Anum_pg_attrdef_adsrc_on_update, adrel->rd_att, &isnull); + if (val && pg_strcasecmp(TextDatumGetCString(val), "") != 0) { + temp_on_update = TRUE; + } + } + systable_endscan(adscan); + heap_close(adrel, RowExclusiveLock); + return temp_on_update; +} + /* * ALTER TABLE ALTER COLUMN SET/DROP DEFAULT */ @@ -10050,32 +10079,7 @@ static void ATExecColumnDefault(Relation rel, const char* colName, Node* newDefa errmsg("column \"%s\" of relation \"%s\" is a generated column", colName, RelationGetRelationName(rel)))); } - HeapTuple htup = NULL; - bool isnull = false; - char* tempUpdateExpr = NULL; - bool on_update = FALSE; - htup = SearchSysCacheCopyAttName(RelationGetRelid(rel), colName); - if (!HeapTupleIsValid(htup)) - ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", colName, RelationGetRelationName(rel)))); - Form_pg_attribute attTup = (Form_pg_attribute)GETSTRUCT(htup); - AttrNumber temp_attnum = attTup->attnum; - - ScanKeyData skey[2]; - Relation adrel = heap_open(AttrDefaultRelationId, RowExclusiveLock); - ScanKeyInit(&skey[0], Anum_pg_attrdef_adrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel))); - ScanKeyInit(&skey[1], Anum_pg_attrdef_adnum, BTEqualStrategyNumber, F_INT2EQ, Int16GetDatum(temp_attnum)); - SysScanDesc adscan = systable_beginscan(adrel, AttrDefaultIndexId, true, NULL, 2, skey); - - if (HeapTupleIsValid(htup = systable_getnext(adscan))) { - Datum val = heap_getattr(htup, Anum_pg_attrdef_adsrc_on_update, adrel->rd_att, &isnull); - if (val && pg_strcasecmp(TextDatumGetCString(val), "") != 0) { - tempUpdateExpr = TextDatumGetCString(val); - on_update = TRUE; - } - } - systable_endscan(adscan); - heap_close(adrel, RowExclusiveLock); + bool on_update = FetchOnUpdateExpress(rel, colName); /* * Remove any old default for the column. We use RESTRICT here for diff --git a/src/gausskernel/runtime/executor/nodeModifyTable.cpp b/src/gausskernel/runtime/executor/nodeModifyTable.cpp index 7d179387f..e35aaaef5 100644 --- a/src/gausskernel/runtime/executor/nodeModifyTable.cpp +++ b/src/gausskernel/runtime/executor/nodeModifyTable.cpp @@ -422,8 +422,7 @@ static bool GetUpdateExprCol(TupleDesc tupdesc, int atti) static void RecoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, CmdType cmdtype) { - Relation rel = resultRelInfo->ri_RelationDesc; - TupleDesc tupdesc = RelationGetDescr(rel); + TupleDesc tupdesc = RelationGetDescr(resultRelInfo->ri_RelationDesc); int natts = tupdesc->natts; MemoryContext oldContext; @@ -446,8 +445,8 @@ static void RecoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, CmdT expr = (Expr *)build_column_default(rel, i + 1, false, true); if (expr == NULL) - elog(ERROR, "no update expression found for column number %d of table \"%s\"", i + 1, - RelationGetRelationName(rel)); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("no update expression found for column number %d of table \"%s\"", i + 1, + RelationGetRelationName(rel)))); resultRelInfo->ri_UpdatedExprs[i] = ExecPrepareExpr(expr, estate); resultRelInfo->ri_NumUpdatedNeeded++; @@ -481,10 +480,6 @@ bool ExecComputeStoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, T int attnum; uint32 updated_colnum_resno; Bitmapset* updatedCols = GetUpdatedColumns(node->resultRelInfo, node->ps.state); - HeapTuple oldtup = GetTupleForTrigger(estate, NULL, resultRelInfo, oldPartitionOid, bucketid, otid, LockTupleShared, NULL); - - RecoredUpdateExpr(resultRelInfo, estate, cmdtype); - /* * If no generated columns have been affected by this change, then skip * the rest. @@ -492,6 +487,10 @@ bool ExecComputeStoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, T if (resultRelInfo->ri_NumUpdatedNeeded == 0) return true; + HeapTuple oldtup = GetTupleForTrigger(estate, NULL, resultRelInfo, oldPartitionOid, bucketid, otid, LockTupleShared, NULL); + + RecoredUpdateExpr(resultRelInfo, estate, cmdtype); + /* compare update operator whether the newtuple is equal to the oldtuple, * if equal, so update don't fix the default column value */ Datum* oldvalues = (Datum*)palloc(natts * sizeof(Datum)); @@ -503,10 +502,6 @@ bool ExecComputeStoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, T temp_id = attnum; for (int32 i = 0; i < (int32)natts; i++) { if (updated_colnum_resno == (i + 1)) { - Form_pg_attribute attr = TupleDescAttr(tupdesc, i); - opfuncoid = OpernameGetOprid(list_make1(makeString("=")), attr->atttypid, attr->atttypid); - RegProcedure oprcode = get_opcode(opfuncoid); - fmgr_info(oprcode, &eqproc); if (slot->tts_isnull[i] && oldnulls[i]) { match = true; } else if (slot->tts_isnull[i] && !oldnulls[i]) { @@ -514,6 +509,10 @@ bool ExecComputeStoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, T } else if (!slot->tts_isnull[i] && oldnulls[i]) { match = false; } else { + Form_pg_attribute attr = TupleDescAttr(tupdesc, i); + opfuncoid = OpernameGetOprid(list_make1(makeString("=")), attr->atttypid, attr->atttypid); + RegProcedure oprcode = get_opcode(opfuncoid); + fmgr_info(oprcode, &eqproc); match = DatumGetBool(FunctionCall2Coll(&eqproc, DEFAULT_COLLATION_OID, slot->tts_values[i], oldvalues[i])); } update_fix_result = update_fix_result && match; @@ -534,8 +533,6 @@ bool ExecComputeStoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, T values = (Datum *)palloc(sizeof(*values) * natts); nulls = (bool *)palloc(sizeof(*nulls) * natts); replaces = (bool *)palloc0(sizeof(*replaces) * natts); - rc = memset_s(replaces, sizeof(bool) * natts, 0, sizeof(bool) * natts); - securec_check(rc, "\0", "\0"); temp_id = -1; attnum = bms_next_member(updatedCols, temp_id); updated_colnum_resno = attnum + FirstLowInvalidHeapAttributeNumber; @@ -553,7 +550,7 @@ bool ExecComputeStoredUpdateExpr(ResultRelInfo *resultRelInfo, EState *estate, T if (GetUpdateExprCol(tupdesc, i) && resultRelInfo->ri_UpdatedExprs[i]) { ExprContext *econtext; Datum val; - bool isnull; + bool isnull = false; econtext = GetPerTupleExprContext(estate); econtext->ecxt_scantuple = slot; @@ -2069,7 +2066,7 @@ TupleTableSlot* ExecUpdate(ItemPointer tupleid, LockTupleMode lockmode; /* acquire Form_pg_attrdef ad_on_update */ - if (result_relation_desc->rd_att->constr && result_relation_desc->rd_att->constr->has_on_update && DB_IS_CMPT(B_FORMAT)) { + if (result_relation_desc->rd_att->constr && result_relation_desc->rd_att->constr->has_on_update) { bool update_fix_result = ExecComputeStoredUpdateExpr(result_rel_info, estate, slot, tuple, CMD_UPDATE, node, tupleid, oldPartitionOid, bucketid); if (!update_fix_result) { tuple = slot->tts_tuple; diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 8229a149d..f88458bdd 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -29,7 +29,7 @@ typedef struct RawColumnDefault { AttrNumber attnum; /* attribute to attach default to */ Node *raw_default; /* default value (untransformed parse tree) */ char generatedCol; /* generated column setting */ - Node *update_expr = NULL; + Node *update_expr; } RawColumnDefault; typedef struct CookedConstraint { @@ -42,7 +42,7 @@ typedef struct CookedConstraint { int inhcount; /* number of times constraint is inherited */ bool is_no_inherit; /* constraint has local def and cannot be * inherited */ - Node *update_expr = NULL; + Node *update_expr; } CookedConstraint; typedef struct CeHeapInfo { diff --git a/src/include/nodes/parsenodes_common.h b/src/include/nodes/parsenodes_common.h index b8b9820e1..bac0a7a17 100644 --- a/src/include/nodes/parsenodes_common.h +++ b/src/include/nodes/parsenodes_common.h @@ -1014,7 +1014,7 @@ typedef struct ColumnDef { Position *position; Form_pg_attribute dropped_attr; /* strcuture for dropped attribute during create table like OE */ char generatedCol; /* generated column setting */ - Node *update_default = NULL; + Node *update_default; } ColumnDef; /* @@ -1326,7 +1326,7 @@ typedef struct Constraint { InformationalConstraint *inforConstraint; char generated_when; /* ALWAYS or BY DEFAULT */ char generated_kind; /* currently always STORED */ - Node *update_expr = NULL; + Node *update_expr; } Constraint; /*