Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.92) (envelope-from ) id 1j6Iwa-00014V-VZ for pgsql-hackers@arkaria.postgresql.org; Mon, 24 Feb 2020 18:59:05 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1j6IwY-0005aO-3y for pgsql-hackers@arkaria.postgresql.org; Mon, 24 Feb 2020 18:59:02 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1j6IwX-0005aH-MK for pgsql-hackers@lists.postgresql.org; Mon, 24 Feb 2020 18:59:01 +0000 Received: from mail-qt1-x843.google.com ([2607:f8b0:4864:20::843]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1j6IwU-0004Px-64 for pgsql-hackers@lists.postgresql.org; Mon, 24 Feb 2020 18:59:00 +0000 Received: by mail-qt1-x843.google.com with SMTP id t13so7297014qto.3 for ; Mon, 24 Feb 2020 10:58:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :content-transfer-encoding:in-reply-to:user-agent; bh=P4ASWq84VjcYTMEpZg/rTiwlt2kjdW+Zj/CxqoXhVaE=; b=vDRDynZzDzrquqSrJ8ejleNpvBUEm8calBsFrTRyL1ip4jvTA3Y4XlMeZAw5us+Uf6 D3XRabyZKN3M9SoVAGsnpWkiYnJA04QB7HUCWkizcxRUrt3xcklKNsP1KozUOO+n8xZC N87t0rBLToKLgQyRdX9DfPpNqr/w+WuUbicou8I9MqdtauteHWxVTSOIIQUw8OHEttpI YCXnAFYPzWjzxU+8zQlFD7JxbRTfOYLL0ul2tHlsmrBzw2RN5qm7sXZB9K8xCCihkiKT 5wmxNUNsn9rfU1lNvUM8i1cYtfeS8wiGMiDcNJjHQnBFoZDGN3ldUl8PKLjm5u4gOiN7 +AiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=P4ASWq84VjcYTMEpZg/rTiwlt2kjdW+Zj/CxqoXhVaE=; b=Oc8njBann2joVf91vOuxdM19nOJrx/Clgc43uwAOW+mTSTk7DEWKRhOFbqdYFw4TE9 Wz0hPnPoik+cUXX1AnddzJbPXJrghLFRS6UvGPorFGq2N4QNQ2LdU6ZTpVNP0+vqLZ42 AUf2CngXyhTfRbNLoAeNaSXtr76YEFlrFrZRxeChk2uc/nnr7GHHQ/GILHlgM8QVpBbS PH4QJkoycSWLNj1hVEnuUDmLpCoS4q1bya8Jd1S/wXXApyJ+M0H/cS7kB6rubZkEsxMx PrYGid7kmsWMh9IozyK+awwDKFZAlLq1w+llXcOBPMvAHpUnnX94UNckgVTEPs4sVGLT Exhw== X-Gm-Message-State: APjAAAWcck1U81Pp+SYBcocZUDpp+qFhJdMN3AemhhpfrWXjHsHeo2mw bZEUcmGoXznUyr77ryFEAoBEXQ== X-Google-Smtp-Source: APXvYqxCh5RNUHbJxKd/751erjMI0S9TYWEc+xHf3aHjUZspJIjYECp2ourN/lj1XooGHLl7DuIEWQ== X-Received: by 2002:ac8:1194:: with SMTP id d20mr48322591qtj.243.1582570736118; Mon, 24 Feb 2020 10:58:56 -0800 (PST) Received: from nimloth.alvh.no-ip.org ([70.32.0.53]) by smtp.gmail.com with ESMTPSA id c10sm6223010qkb.4.2020.02.24.10.58.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Feb 2020 10:58:55 -0800 (PST) Received: by nimloth.alvh.no-ip.org (Postfix, from userid 1000) id BA5AC3007EE; Mon, 24 Feb 2020 15:58:50 -0300 (-03) Date: Mon, 24 Feb 2020 15:58:50 -0300 From: Alvaro Herrera To: Amit Langote Cc: Pg Hackers , Tom Lane Subject: Re: pg_trigger.tgparentid Message-ID: <20200224185850.GA30899@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="vkogqOf2sHV7VnPd" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --vkogqOf2sHV7VnPd Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit On 2020-Feb-19, Amit Langote wrote: > Or: > > * However, if our parent is a partition itself, there might be > * internal triggers that must not be skipped. For example, triggers > * on the parent that were in turn cloned from its own parent are > * marked internal, which must be cloned to the partition. Thanks for pointing this out -- I agree it needed rewording. I slightly adjusted your text like this: * Internal triggers require careful examination. Ideally, we don't * clone them. However, if our parent is itself a partition, there * might be internal triggers that must not be skipped; for example, * triggers on our parent that are in turn clones from its parent (our * grandparent) are marked internal, yet they are to be cloned. Is this okay for you? Tom Lane wrote: > It'd be nice if the term "parent trigger" were defined somewhere in > this. Seems all right otherwise. Fair point. I propose to patch catalog.sgml like this Parent trigger that this trigger is cloned from, zero if not a clone; this happens when partitions are created or attached to a partitioned table. It's perhaps not great to have to explain the parentage concept in the catalog docs, so I'm going to go over the other documentation pages (trigger.sgml and ref/create_trigger.sgml) to see whether they need any patching; it's possible that we neglected to update them properly when the partitioning-related commits went it. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --vkogqOf2sHV7VnPd Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v2-0001-Record-parents-of-triggers.patch" From ff13d7004c9ee77ba411ace405224188aa0c353c Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 17 Feb 2020 17:34:47 -0300 Subject: [PATCH v2] Record parents of triggers This let us get rid of a recently introduced ugly hack (commit 1fa846f1c9af). --- doc/src/sgml/catalogs.sgml | 11 ++++++ src/backend/commands/tablecmds.c | 59 +++----------------------------- src/backend/commands/trigger.c | 1 + src/include/catalog/pg_trigger.h | 1 + 4 files changed, 18 insertions(+), 54 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index a10b66569b..34bc0d0526 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -6951,6 +6951,17 @@ SCRAM-SHA-256$<iteration count>:&l The table this trigger is on + + tgparentid + oid + pg_trigger.oid + + Parent trigger that this trigger is cloned from, zero if not a clone; + this happens when partitions are created or attached to a partitioned + table. + + + tgname name diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b7c8d663fc..02a7c04fdb 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -16447,54 +16447,6 @@ out: MemoryContextDelete(cxt); } -/* - * isPartitionTrigger - * Subroutine for CloneRowTriggersToPartition: determine whether - * the given trigger has been cloned from another one. - * - * We use pg_depend as a proxy for this, since we don't have any direct - * evidence. This is an ugly hack to cope with a catalog deficiency. - * Keep away from children. Do not stare with naked eyes. Do not propagate. - */ -static bool -isPartitionTrigger(Oid trigger_oid) -{ - Relation pg_depend; - ScanKeyData key[2]; - SysScanDesc scan; - HeapTuple tup; - bool found = false; - - pg_depend = table_open(DependRelationId, AccessShareLock); - - ScanKeyInit(&key[0], Anum_pg_depend_classid, - BTEqualStrategyNumber, - F_OIDEQ, - ObjectIdGetDatum(TriggerRelationId)); - ScanKeyInit(&key[1], Anum_pg_depend_objid, - BTEqualStrategyNumber, - F_OIDEQ, - ObjectIdGetDatum(trigger_oid)); - - scan = systable_beginscan(pg_depend, DependDependerIndexId, - true, NULL, 2, key); - while ((tup = systable_getnext(scan)) != NULL) - { - Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(tup); - - if (dep->refclassid == TriggerRelationId) - { - found = true; - break; - } - } - - systable_endscan(scan); - table_close(pg_depend, AccessShareLock); - - return found; -} - /* * CloneRowTriggersToPartition * subroutine for ATExecAttachPartition/DefineRelation to create row @@ -16537,11 +16489,10 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) /* * Internal triggers require careful examination. Ideally, we don't - * clone them. - * - * However, if our parent is a partitioned relation, there might be - * internal triggers that need cloning. In that case, we must skip - * clone it if the trigger on parent depends on another trigger. + * clone them. However, if our parent is itself a partition, there + * might be internal triggers that must not be skipped; for example, + * triggers on our parent that are in turn clones from its parent (our + * grandparent) are marked internal, yet they are to be cloned. * * Note we dare not verify that the other trigger belongs to an * ancestor relation of our parent, because that creates deadlock @@ -16549,7 +16500,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) */ if (trigForm->tgisinternal && (!parent->rd_rel->relispartition || - !isPartitionTrigger(trigForm->oid))) + !OidIsValid(trigForm->tgparentid))) continue; /* diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index b9b1262e30..6e8b7223fe 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -847,6 +847,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid); values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); + values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid); values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein, CStringGetDatum(trigname)); values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid); diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h index 2f30c7c2f9..9612b9bdd6 100644 --- a/src/include/catalog/pg_trigger.h +++ b/src/include/catalog/pg_trigger.h @@ -35,6 +35,7 @@ CATALOG(pg_trigger,2620,TriggerRelationId) { Oid oid; /* oid */ Oid tgrelid; /* relation trigger is attached to */ + Oid tgparentid; /* OID of parent trigger, if any */ NameData tgname; /* trigger's name */ Oid tgfoid; /* OID of function to be called */ int16 tgtype; /* BEFORE/AFTER/INSTEAD, UPDATE/DELETE/INSERT, -- 2.20.1 --vkogqOf2sHV7VnPd--