/* Build scankey for every non-expression attribute in the index. */ for (index_attoff = 0; index_attoff < IndexRelationGetNumberOfKeyAttributes(idxrel);
index_attoff++)
{
Oid operator;
Oid optype;
Oid opfamily;
RegProcedure regop; int table_attno = indkey->values[index_attoff];
StrategyNumber eq_strategy;
if (!AttributeNumberIsValid(table_attno))
{ /* *XXX:Currently,wedon'tsupportexpressionsinthescankey, *seecodebelow.
*/ continue;
}
switch (res)
{ case TM_Ok: break; case TM_Updated: /* XXX: Improve handling here */ if (ItemPointerIndicatesMovedPartitions(&tmfd->ctid))
ereport(LOG,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("tuple to be locked was already moved to another partition due to concurrent update, retrying"))); else
ereport(LOG,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("concurrent update, retrying")));
refetch = true; break; case TM_Deleted: /* XXX: Improve handling here */
ereport(LOG,
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
errmsg("concurrent delete, retrying")));
refetch = true; break; case TM_Invisible:
elog(ERROR, "attempted to lock invisible tuple"); break; default:
elog(ERROR, "unexpected table_tuple_lock status: %u", res); break;
}
/* Check equality of the attributes. */ for (attrnum = 0; attrnum < slot1->tts_tupleDescriptor->natts; attrnum++)
{
Form_pg_attribute att;
TypeCacheEntry *typentry;
att = TupleDescAttr(slot1->tts_tupleDescriptor, attrnum);
/* *Ignoredroppedandgeneratedcolumnsasthepublisherdoesn'tsend *those
*/ if (att->attisdropped || att->attgenerated) continue;
/* *IfonevalueisNULLandotherisnot,thentheyarecertainlynot *equal
*/ if (slot1->tts_isnull[attrnum] != slot2->tts_isnull[attrnum]) returnfalse;
/* *IfbothareNULL,theycanbeconsideredequal.
*/ if (slot1->tts_isnull[attrnum] || slot2->tts_isnull[attrnum]) continue;
typentry = eq[attrnum]; if (typentry == NULL)
{
typentry = lookup_type_cache(att->atttypid,
TYPECACHE_EQ_OPR_FINFO); if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not identify an equality operator for type %s",
format_type_be(att->atttypid))));
eq[attrnum] = typentry;
}
if (!DatumGetBool(FunctionCall2Coll(&typentry->eq_opr_finfo,
att->attcollation,
slot1->tts_values[attrnum],
slot2->tts_values[attrnum]))) returnfalse;
}
/* Try to find the tuple */ while (table_scan_getnextslot(scan, ForwardScanDirection, scanslot))
{ if (!tuples_equal(scanslot, searchslot, eq)) continue;
/* Check the constraints of the tuple */ if (rel->rd_att->constr)
ExecConstraints(resultRelInfo, slot, estate); if (rel->rd_rel->relispartition)
ExecPartitionCheck(resultRelInfo, slot, estate, true);
/* OK, store the tuple and create index entries for it */
simple_table_tuple_insert(resultRelInfo->ri_RelationDesc, slot);
/* Check the constraints of the tuple */ if (rel->rd_att->constr)
ExecConstraints(resultRelInfo, slot, estate); if (rel->rd_rel->relispartition)
ExecPartitionCheck(resultRelInfo, slot, estate, true);
/* *Skipcheckingthereplicaidentityforpartitionedtables,becausethe *operationsareactuallyperformedontheleafpartitions.
*/ if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) return;
/* We only need to do checks for UPDATE and DELETE. */ if (cmd != CMD_UPDATE && cmd != CMD_DELETE) return;
/* *ItisonlysafetoexecuteUPDATE/DELETEiftherelationdoesnot *publishUPDATEsorDELETEs,orallthefollowingconditionsare *satisfied: * *1.Allcolumns,referencedintherowfiltersfrompublicationswhich *therelationisin,arevalid-i.e.whenallreferencedcolumnsare *partofREPLICAIDENTITY. * *2.Allcolumns,referencedinthecolumnlistsarevalid-i.e.when *allcolumnsreferencedintheREPLICAIDENTITYarecoveredbythe *columnlist. * *3.AllgeneratedcolumnsinREPLICAIDENTITYoftherelation,arevalid *-i.e.whenallthesegeneratedcolumnsarepublished. * *XXXWecouldoptimizeitbyfirstcheckingwhetheranyofthe *publicationshavearowfilterorcolumnlistforthisrelation,orif *therelationcontainsageneratedcolumn.Ifnoneoftheseexistand *therelationhasreplicaidentitythenwecanavoidbuildingthe *descriptorbutasthishappensonlyonetimeitdoesn'tseemworththe *additionalcomplexity.
*/
RelationBuildPublicationDesc(rel, &pubdesc); if (cmd == CMD_UPDATE && !pubdesc.rf_valid_for_update)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot update table \"%s\"",
RelationGetRelationName(rel)),
errdetail("Column used in the publication WHERE expression is not part of the replica identity."))); elseif (cmd == CMD_UPDATE && !pubdesc.cols_valid_for_update)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot update table \"%s\"",
RelationGetRelationName(rel)),
errdetail("Column list used by the publication does not cover the replica identity."))); elseif (cmd == CMD_UPDATE && !pubdesc.gencols_valid_for_update)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot update table \"%s\"",
RelationGetRelationName(rel)),
errdetail("Replica identity must not contain unpublished generated columns."))); elseif (cmd == CMD_DELETE && !pubdesc.rf_valid_for_delete)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot delete from table \"%s\"",
RelationGetRelationName(rel)),
errdetail("Column used in the publication WHERE expression is not part of the replica identity."))); elseif (cmd == CMD_DELETE && !pubdesc.cols_valid_for_delete)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot delete from table \"%s\"",
RelationGetRelationName(rel)),
errdetail("Column list used by the publication does not cover the replica identity."))); elseif (cmd == CMD_DELETE && !pubdesc.gencols_valid_for_delete)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("cannot delete from table \"%s\"",
RelationGetRelationName(rel)),
errdetail("Replica identity must not contain unpublished generated columns.")));
/* If relation has replica identity we are always good. */ if (OidIsValid(RelationGetReplicaIndex(rel))) return;
/* REPLICA IDENTITY FULL is also good for UPDATE/DELETE. */ if (rel->rd_rel->relreplident == REPLICA_IDENTITY_FULL) return;
/* *ThisisUPDATE/DELETEandthereisnoreplicaidentity. * *CheckifthetablepublishesUPDATESorDELETES.
*/ if (cmd == CMD_UPDATE && pubdesc.pubactions.pubupdate)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot update table \"%s\" because it does not have a replica identity and publishes updates",
RelationGetRelationName(rel)),
errhint("To enable updating the table, set REPLICA IDENTITY using ALTER TABLE."))); elseif (cmd == CMD_DELETE && pubdesc.pubactions.pubdelete)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("cannot delete from table \"%s\" because it does not have a replica identity and publishes deletes",
RelationGetRelationName(rel)),
errhint("To enable deleting from the table, set REPLICA IDENTITY using ALTER TABLE.")));
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.