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.89) (envelope-from ) id 1j0A6a-000297-9m for pgsql-bugs@arkaria.postgresql.org; Fri, 07 Feb 2020 20:20:00 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1j0A6X-0007sH-R7 for pgsql-bugs@arkaria.postgresql.org; Fri, 07 Feb 2020 20:19:57 +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 1j0A6X-0007s9-F4 for pgsql-bugs@lists.postgresql.org; Fri, 07 Feb 2020 20:19:57 +0000 Received: from mail-qk1-x744.google.com ([2607:f8b0:4864:20::744]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1j0A6T-0004oB-G5 for pgsql-bugs@lists.postgresql.org; Fri, 07 Feb 2020 20:19:56 +0000 Received: by mail-qk1-x744.google.com with SMTP id q15so347591qke.9 for ; Fri, 07 Feb 2020 12:19:52 -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=/P68VS06TDyxKlTT93L/x0SmmyVKFcDHUEpDnD/nheM=; b=KoVxlXNJF30vJteRuSxhifQCKB11ydsf9TpbORgr9nBKXvNpp3ZRwkD3kjgLsWirhn aegjY4stgI7P3bTvp0VhfmeiyphlU+dk0Y47KZt1e0ehZmh51TzDZADMv6cGOvX63HmI Lmgv0jeTwOB5yoUo+sWarA2G10y83xsBoPTrP6ckGFaIiky2sBxLv1CjwDAGakm1+Xxu 3Ev7lUe6et+uxaoE3/sjuD6/iWF9VQeeHG4es015bl80mbuLI4hNMhM6lhklDQUxKLZN 0XxhjhI+iuUIMn+sDySMO7pjdqI2xeqKzW7g2j7mtRlepfeyZxbr4ONei6+RK7+XruI5 25fw== 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=/P68VS06TDyxKlTT93L/x0SmmyVKFcDHUEpDnD/nheM=; b=YGd4smJ7I6tBwIBf7jgJhDHFpEpLBSYGyVLpXD3RPBBsgfXG1AltPo8ZS5c11Xqihr TBxPunfRjNJpirNTNGrOhyakpC4D6eu0Axib+uC8EATU7jp9Xujc8ENCefLgInyQixhj tSbHtbNKiZWfGStB4x90g0KqkZZY07zF05XC0j1pxq1CTWYSYSuXhJOeDLwsfKCpxMgp KikyL0nFCdoroXuRBLYIkhUpxJmvIGTlQTYE6wj/6UmyeOngfPc+glD1rYtAz9n761a7 f0JmGGqf16XS4/yIAS1ugBwLjDA4jJWHWZ52007KGBA3w4vLHI3te8e0gzJL1+fzf2rN nIHw== X-Gm-Message-State: APjAAAVM/TBUbG51+wWkGRYPu8dpfiSYNCbTgvv1wpQSEJobbUfA2fNi zh2hgkSlO5jxhOUBiEwjPYIyhn3qZLg= X-Google-Smtp-Source: APXvYqywJ8IuzqU4nWRFDavl9/eT1F1Z0UcAAY6KSAkCZaoojKn5/ekNKQ8gUmWdzfCPh/lPnMn2Ng== X-Received: by 2002:a37:742:: with SMTP id 63mr652264qkh.31.1581106791429; Fri, 07 Feb 2020 12:19:51 -0800 (PST) Received: from nimloth.alvh.no-ip.org ([190.217.182.22]) by smtp.gmail.com with ESMTPSA id z5sm2046773qta.7.2020.02.07.12.19.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Feb 2020 12:19:50 -0800 (PST) Received: by nimloth.alvh.no-ip.org (Postfix, from userid 1000) id 63303300930; Fri, 7 Feb 2020 17:19:48 -0300 (-03) Date: Fri, 7 Feb 2020 17:19:48 -0300 From: Alvaro Herrera To: Jehan-Guillaume de Rorthais Cc: pgsql-bugs@lists.postgresql.org Subject: Re: FK violation in partitioned table after truncating a referenced partition Message-ID: <20200207201948.GA16783@alvherre.pgsql> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20200207192257.1145eadd@firost> User-Agent: Mutt/1.10.1 (2018-07-13) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk There's another key point I forgot -- which is that we only need to search for constraints on the topmost partitioned table, not each of its partitions. The reason is that pg_constraint rows exist on the other side that reference that relation, for each partition on the other side. So we can do this: + if (HeapTupleIsValid(tuple)) + { + Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple); + + /* + * pg_constraint rows always appear for partitioned hierarchies + * this way: on the each side of the constraint, one row appears + * for each partition that points to the top-most table on the + * other side. + * + * Because of this arrangement, we can correctly catch all + * relevant relations by adding to 'parent_cons' all rows with + * valid conparentid, and to the 'oids' list all rows with a + * zero conparentid. If any oids are added to 'oids', redo the + * first loop above by setting 'restart'. + */ + if (OidIsValid(con->conparentid)) + parent_cons = list_append_unique_oid(parent_cons, + con->conparentid); + else if (!list_member_oid(oids, con->confrelid)) + { + oids = lappend_oid(oids, con->confrelid); + restart = true; + } + } that is, keep appending to the parent_cons list, and not touch the oids list, until we get to the top of the hierarchy. Then when we redo the first loop, we'll get all partitions on the other side because they all have pg_constraint rows that reference the topmost rel. (That is to say, all the intermediate-partition OIDs should be useless in the 'oids' list anyway.) -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services