/* *Informationusedtovalidatethecolumnsintherowfilterexpression.See *contain_invalid_rfcolumn_walkerfordetails.
*/ typedefstruct rf_context
{
Bitmapset *bms_replident; /* bitset of replica identity columns */ bool pubviaroot; /* true if we are validating the parent
* relation's row filter */
Oid relid; /* relid of the relation */
Oid parentid; /* relid of the parent relation */
} rf_context;
static List *OpenTableList(List *tables); staticvoid CloseTableList(List *rels); staticvoid LockSchemaList(List *schemalist); staticvoid PublicationAddTables(Oid pubid, List *rels, bool if_not_exists,
AlterPublicationStmt *stmt); staticvoid PublicationDropTables(Oid pubid, List *rels, bool missing_ok); staticvoid PublicationAddSchemas(Oid pubid, List *schemas, bool if_not_exists,
AlterPublicationStmt *stmt); staticvoid PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok); staticchar defGetGeneratedColsOption(DefElem *def);
if (!SplitIdentifierString(publish, ',', &publish_list))
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid list syntax in parameter \"%s\"", "publish")));
/* Process the option list. */
foreach(lc2, publish_list)
{ char *publish_opt = (char *) lfirst(lc2);
/* *ConvertthePublicationObjSpecTypelistintoschemaoidlistand *PublicationTablelist.
*/ staticvoid
ObjectsInPublicationToOids(List *pubobjspec_list, ParseState *pstate,
List **rels, List **schemas)
{
ListCell *cell;
PublicationObjSpec *pubobj;
if (!pubobjspec_list) return;
foreach(cell, pubobjspec_list)
{
Oid schemaid;
List *search_path;
pubobj = (PublicationObjSpec *) lfirst(cell);
switch (pubobj->pubobjtype)
{ case PUBLICATIONOBJ_TABLE:
*rels = lappend(*rels, pubobj->pubtable); break; case PUBLICATIONOBJ_TABLES_IN_SCHEMA:
schemaid = get_namespace_oid(pubobj->name, false);
/* Filter out duplicates if user specifies "sch1, sch1" */
*schemas = list_append_unique_oid(*schemas, schemaid); break; case PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA:
search_path = fetch_search_path(false); if (search_path == NIL) /* nothing valid in search_path? */
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_SCHEMA),
errmsg("no schema has been selected for CURRENT_SCHEMA"));
if (!OidIsValid(publish_as_relid))
publish_as_relid = relid;
}
/* Fetch the column list */
pub = GetPublication(pubid);
check_and_fetch_column_list(pub, publish_as_relid, NULL, &columns);
if (relation->rd_rel->relreplident == REPLICA_IDENTITY_FULL)
{ /* With REPLICA IDENTITY FULL, no column list is allowed. */
*invalid_column_list = (columns != NULL);
switch (nodeTag(node))
{ case T_Var: /* System columns are not allowed. */ if (((Var *) node)->varattno < InvalidAttrNumber)
errdetail_msg = _("System columns are not allowed."); break; case T_OpExpr: case T_DistinctExpr: case T_NullIfExpr: /* OK, except user-defined operators are not allowed. */ if (((OpExpr *) node)->opno >= FirstNormalObjectId)
errdetail_msg = _("User-defined operators are not allowed."); break; case T_ScalarArrayOpExpr: /* OK, except user-defined operators are not allowed. */ if (((ScalarArrayOpExpr *) node)->opno >= FirstNormalObjectId)
errdetail_msg = _("User-defined operators are not allowed.");
/* OK, except user-defined operators are not allowed. */
foreach(opid, ((RowCompareExpr *) node)->opnos)
{ if (lfirst_oid(opid) >= FirstNormalObjectId)
{
errdetail_msg = _("User-defined operators are not allowed."); break;
}
}
} break; case T_Const: case T_FuncExpr: case T_BoolExpr: case T_RelabelType: case T_CollateExpr: case T_CaseExpr: case T_CaseTestExpr: case T_ArrayExpr: case T_RowExpr: case T_CoalesceExpr: case T_MinMaxExpr: case T_XmlExpr: case T_NullTest: case T_BooleanTest: case T_List: /* OK, supported */ break; default:
errdetail_msg = _("Only columns, constants, built-in operators, built-in data types, built-in collations, and immutable built-in functions are allowed."); break;
}
/* *Forallthesupportednodes,ifwehaven'talreadyfoundaproblem, *checkthetypes,functions,andcollationsusedinit.WecheckList *bywalkingthrougheachelement.
*/ if (!errdetail_msg && !IsA(node, List))
{ if (exprType(node) >= FirstNormalObjectId)
errdetail_msg = _("User-defined types are not allowed."); elseif (check_functions_in_node(node, contain_mutable_or_user_functions_checker,
pstate))
errdetail_msg = _("User-defined or built-in mutable functions are not allowed."); elseif (exprCollation(node) >= FirstNormalObjectId ||
exprInputCollation(node) >= FirstNormalObjectId)
errdetail_msg = _("User-defined collations are not allowed.");
}
/* *Ifwefoundaprobleminthisnode,throwerrornow.Otherwisekeep *going.
*/ if (errdetail_msg)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("invalid publication WHERE expression"),
errdetail_internal("%s", errdetail_msg),
parser_errposition(pstate, exprLocation(node))));
/* *Ifthepublicationdoesn'tpublishchangesviatherootpartitioned *table,thepartition'srowfilterwillbeused.Sodisallowusing *WHEREclauseonpartitionedtableinthiscase.
*/ if (!pubviaroot &&
pri->relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot use publication WHERE clause for relation \"%s\"",
RelationGetRelationName(pri->relation)),
errdetail("WHERE clause cannot be used for a partitioned table when %s is false.", "publish_via_partition_root")));
/* *Disallowspecifyingcolumnlistifanyschemaisinthe *publication. * *XXXWecouldinsteadjustforbidthecasewhenthepublication *triestopublishthetablewithacolumnlistandaschemaforthat *table.However,ifwedothatthenweneedarestrictionduring *ALTERTABLE...SETSCHEMAtopreventsuchacasewhichdoesn't *seemtobeagoodidea.
*/ if (publish_schema)
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot use column list for relation \"%s.%s\" in publication \"%s\"",
get_namespace_name(RelationGetNamespace(pri->relation)),
RelationGetRelationName(pri->relation), pubname),
errdetail("Column lists cannot be specified in publications containing FOR TABLES IN SCHEMA elements."));
/* *Ifthepublicationdoesn'tpublishchangesviatherootpartitioned *table,thepartition'scolumnlistwillbeused.Sodisallowusing *acolumnlistonthepartitionedtableinthiscase.
*/ if (!pubviaroot &&
pri->relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot use column list for relation \"%s.%s\" in publication \"%s\"",
get_namespace_name(RelationGetNamespace(pri->relation)),
RelationGetRelationName(pri->relation), pubname),
errdetail("Column lists cannot be specified for partitioned tables when %s is false.", "publish_via_partition_root")));
}
}
/* must have CREATE privilege on database */
aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, GetUserId(), ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_DATABASE,
get_database_name(MyDatabaseId));
/* FOR ALL TABLES requires superuser */ if (stmt->for_all_tables && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to create FOR ALL TABLES publication")));
/* Check if name is used */
puboid = GetSysCacheOid1(PUBLICATIONNAME, Anum_pg_publication_oid,
CStringGetDatum(stmt->pubname)); if (OidIsValid(puboid))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("publication \"%s\" already exists",
stmt->pubname)));
/* Form a tuple. */
memset(values, 0, sizeof(values));
memset(nulls, false, sizeof(nulls));
/* Make the changes visible. */
CommandCounterIncrement();
/* Associate objects with the publication. */ if (stmt->for_all_tables)
{ /* Invalidate relcache so that publication info is rebuilt. */
CacheInvalidateRelcacheAll();
} else
{
ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations,
&schemaidlist);
/* FOR TABLES IN SCHEMA requires superuser */ if (schemaidlist != NIL && !superuser())
ereport(ERROR,
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to create FOR TABLES IN SCHEMA publication"));
if (wal_level != WAL_LEVEL_LOGICAL)
ereport(WARNING,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("\"wal_level\" is insufficient to publish logical changes"),
errhint("Set \"wal_level\" to \"logical\" before creating subscriptions.")));
if (has_rowfilter)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot set parameter \"%s\" to false for publication \"%s\"", "publish_via_partition_root",
stmt->pubname),
errdetail("The publication contains a WHERE clause for partitioned table \"%s\", which is not allowed when \"%s\" is false.",
relname, "publish_via_partition_root")));
Assert(has_collist);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot set parameter \"%s\" to false for publication \"%s\"", "publish_via_partition_root",
stmt->pubname),
errdetail("The publication contains a column list for partitioned table \"%s\", which is not allowed when \"%s\" is false.",
relname, "publish_via_partition_root")));
}
}
/* Everything ok, form a new tuple. */
memset(values, 0, sizeof(values));
memset(nulls, false, sizeof(nulls));
memset(replaces, false, sizeof(replaces));
/* look up the cache for the old relmap */
rftuple = SearchSysCache2(PUBLICATIONRELMAP,
ObjectIdGetDatum(oldrelid),
ObjectIdGetDatum(pubid));
/* *SeeiftheexistingrelationcurrentlyhasaWHEREclauseora *columnlist.Weneedtocomparethosetoo.
*/ if (HeapTupleIsValid(rftuple))
{ bool isnull = true;
Datum whereClauseDatum;
Datum columnListDatum;
/* Load the WHERE clause for this table. */
whereClauseDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
Anum_pg_publication_rel_prqual,
&isnull); if (!isnull)
oldrelwhereclause = stringToNode(TextDatumGetCString(whereClauseDatum));
/* Transform the int2vector column list to a bitmap. */
columnListDatum = SysCacheGetAttr(PUBLICATIONRELMAP, rftuple,
Anum_pg_publication_rel_prattrs,
&isnull);
if (!isnull)
oldcolumns = pub_collist_to_bitmapset(NULL, columnListDatum, NULL);
/* *Disallowaddingschemaifcolumnlistisalreadypartofthe *publication.SeeCheckPubRelationColumnList.
*/ if (!heap_attisnull(coltuple, Anum_pg_publication_rel_prattrs, NULL))
ereport(ERROR,
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot add schema to publication \"%s\"",
stmt->pubname),
errdetail("Schemas cannot be added if any tables that specify a column list are already part of the publication."));
/* *Checkifrelationsandschemascanbeinagivenpublicationandthrow *appropriateerrorifnot.
*/ staticvoid
CheckAlterPublication(AlterPublicationStmt *stmt, HeapTuple tup,
List *tables, List *schemaidlist)
{
Form_pg_publication pubform = (Form_pg_publication) GETSTRUCT(tup);
if ((stmt->action == AP_AddObjects || stmt->action == AP_SetObjects) &&
schemaidlist && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to add or set schemas")));
/* *Checkthatuserisallowedtomanipulatethepublicationtablesin *schema
*/ if (schemaidlist && pubform->puballtables)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("publication \"%s\" is defined as FOR ALL TABLES",
NameStr(pubform->pubname)),
errdetail("Schemas cannot be added to or dropped from FOR ALL TABLES publications.")));
/* Check that user is allowed to manipulate the publication tables. */ if (tables && pubform->puballtables)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("publication \"%s\" is defined as FOR ALL TABLES",
NameStr(pubform->pubname)),
errdetail("Tables cannot be added to or dropped from FOR ALL TABLES publications.")));
}
if (!HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("publication \"%s\" does not exist",
stmt->pubname)));
pubform = (Form_pg_publication) GETSTRUCT(tup);
/* must be owner */ if (!object_ownercheck(PublicationRelationId, pubform->oid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
stmt->pubname);
if (stmt->options)
AlterPublicationOptions(pstate, stmt, rel, tup); else
{
List *relations = NIL;
List *schemaidlist = NIL;
Oid pubid = pubform->oid;
/* *Filteroutduplicatesifuserspecifies"foo,foo". * *Notethatthisalgorithmisknowntonotbeveryefficient(O(N^2)) *butgiventhatitonlyworksonlistoftablesgiventousbyuser *it'sdeemedacceptable.
*/ if (list_member_oid(relids, myrelid))
{ /* Disallow duplicate tables if there are any with row filters. */ if (t->whereClause || list_member_oid(relids_with_rf, myrelid))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("conflicting or redundant WHERE clauses for table \"%s\"",
RelationGetRelationName(rel))));
/* Disallow duplicate tables if there are any with column lists. */ if (t->columns || list_member_oid(relids_with_collist, myrelid))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("conflicting or redundant column lists for table \"%s\"",
RelationGetRelationName(rel))));
foreach(lc, schemalist)
{
Oid schemaid = lfirst_oid(lc);
/* Allow query cancel in case this takes a long time */
CHECK_FOR_INTERRUPTS();
LockDatabaseObject(NamespaceRelationId, schemaid, 0, AccessShareLock);
/* *Itispossiblethatbythetimeweacquirethelockonschema, *concurrentDDLhasremovedit.Wecantestthisbycheckingthe *existenceofschema.
*/ if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(schemaid)))
ereport(ERROR,
errcode(ERRCODE_UNDEFINED_SCHEMA),
errmsg("schema with OID %u does not exist", schemaid));
}
}
/* Must be owner of the table or superuser. */ if (!object_ownercheck(RelationRelationId, RelationGetRelid(rel), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, get_relkind_objtype(rel->rd_rel->relkind),
RelationGetRelationName(rel));
if (pubrel->columns)
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("column list must not be specified in ALTER PUBLICATION ... DROP"));
prid = GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
ObjectIdGetDatum(relid),
ObjectIdGetDatum(pubid)); if (!OidIsValid(prid))
{ if (missing_ok) continue;
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("relation \"%s\" is not part of the publication",
RelationGetRelationName(rel))));
}
if (pubrel->whereClause)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cannot use a WHERE clause when removing a table from a publication")));
/* *Removelistedschemasfromthepublication.
*/ staticvoid
PublicationDropSchemas(Oid pubid, List *schemas, bool missing_ok)
{
ObjectAddress obj;
ListCell *lc;
Oid psid;
foreach(lc, schemas)
{
Oid schemaid = lfirst_oid(lc);
psid = GetSysCacheOid2(PUBLICATIONNAMESPACEMAP,
Anum_pg_publication_namespace_oid,
ObjectIdGetDatum(schemaid),
ObjectIdGetDatum(pubid)); if (!OidIsValid(psid))
{ if (missing_ok) continue;
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tables from schema \"%s\" are not part of the publication",
get_namespace_name(schemaid))));
}
/* Must be owner */ if (!object_ownercheck(PublicationRelationId, form->oid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_PUBLICATION,
NameStr(form->pubname));
/* Must be able to become new owner */
check_can_set_role(GetUserId(), newOwnerId);
/* New owner must have CREATE privilege on database */
aclresult = object_aclcheck(DatabaseRelationId, MyDatabaseId, newOwnerId, ACL_CREATE); if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, OBJECT_DATABASE,
get_database_name(MyDatabaseId));
if (form->puballtables && !superuser_arg(newOwnerId))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to change owner of publication \"%s\"",
NameStr(form->pubname)),
errhint("The owner of a FOR ALL TABLES publication must be a superuser.")));
if (!superuser_arg(newOwnerId) && is_schema_publication(form->oid))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to change owner of publication \"%s\"",
NameStr(form->pubname)),
errhint("The owner of a FOR TABLES IN SCHEMA publication must be a superuser.")));
}
/* *Aparametervalueisrequired.
*/ if (def->arg)
{
sval = defGetString(def);
if (pg_strcasecmp(sval, "none") == 0) return PUBLISH_GENCOLS_NONE; if (pg_strcasecmp(sval, "stored") == 0) return PUBLISH_GENCOLS_STORED;
}
ereport(ERROR,
errcode(ERRCODE_SYNTAX_ERROR),
errmsg("invalid value for publication parameter \"%s\": \"%s\"", def->defname, sval),
errdetail("Valid values are \"%s\" and \"%s\".", "none", "stored"));
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.49Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-08-08)
¤
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.