Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1ewwpN-0000SE-6q for pgsql-hackers@arkaria.postgresql.org; Fri, 16 Mar 2018 21:23:53 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1ewwpL-0003ph-QL for pgsql-hackers@arkaria.postgresql.org; Fri, 16 Mar 2018 21:23:51 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1ewwpL-0003pX-G9 for pgsql-hackers@lists.postgresql.org; Fri, 16 Mar 2018 21:23:51 +0000 Received: from new1-smtp.messagingengine.com ([66.111.4.221]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1ewwpI-000730-5O for pgsql-hackers@postgresql.org; Fri, 16 Mar 2018 21:23:50 +0000 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailnew.nyi.internal (Postfix) with ESMTP id D405315A6; Fri, 16 Mar 2018 17:23:46 -0400 (EDT) Received: from frontend2 ([10.202.2.161]) by compute4.internal (MEProxy); Fri, 16 Mar 2018 17:23:46 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; bh=o+UhmK32Ym/fXZyWY qXSUNclik/h6cJZVTI4tNi9wZ0=; b=l1aLKk+lOvgi7wMzHAWiRv5WD/APO03js Opx4eACYsJO67uJdpiaqlhWlnYRidb1HKPofgEIKqD0T8P7rEXtp+d0mFPrzPqWN kPhEzfc+kjSvE+Wa3O584ru1Im3p+75mT6kQgLLFtGY4PVS6kZUx1MI/mI7/L3Ss E80J5yuNzUa7h38kg6feDEVn3Q/8A7H1BhXW0wKz/0TSPZcH8nZsSkg/cjD3kKOs xIeQwX173cehrIJM84xWmD7/8WI/K8QN37mNMepru3xBUrL1XI2KB9F3FfEIuP2q vhVYtz0pmNfWpBha1mjkSCYz93IZaS+OAHXSgxETMsLwvH0UXYQKg== X-ME-Sender: Received: from alvin.alvh.no-ip.org (unknown [179.56.29.253]) by mail.messagingengine.com (Postfix) with ESMTPA id 23C38241D4; Fri, 16 Mar 2018 17:23:46 -0400 (EDT) Received: by alvin.alvh.no-ip.org (Postfix, from userid 1000) id 75EE7CC2; Fri, 16 Mar 2018 18:23:44 -0300 (-03) Date: Fri, 16 Mar 2018 18:23:44 -0300 From: Alvaro Herrera To: Pavan Deolasee Cc: Etsuro Fujita , Amit Langote , Pg Hackers , Peter Geoghegan , Andres Freund Subject: Re: ON CONFLICT DO UPDATE for partitioned tables Message-ID: <20180316212344.e5hipioljibtx3xw@alvherre.pgsql> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180316151303.rml2p5wffn3o6qy6@alvherre.pgsql> User-Agent: NeoMutt/20170306-137-4415bd-dirty (1.8.0) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Another thing I noticed is that the split of the ON CONFLICT slot and its corresponding projection is pretty weird. The projection is in ResultRelInfo, but the slot itself is in ModifyTableState. You can't make the projection work without a corresponding slot initialized with the correct descriptor, so splitting it this way doesn't make a lot of sense to me. (Now, TBH the split between resultRelInfo->ri_projectReturning and ModifyTableState->ps.ps_ResultTupleSlot, which is the slot that the returning project uses, doesn't make a lot of sense to me either; so maybe there some reason that I'm just not seeing. But I digress.) So I want to propose that we move the slot to be together with the projection node that it serves, ie. we put the slot in ResultRelInfo: typedef struct ResultRelInfo { ... /* for computing ON CONFLICT DO UPDATE SET */ TupleTableSlot *ri_onConflictProjSlot; ProjectionInfo *ri_onConflictSetProj; and with this the structure makes more sense. So ExecInitModifyTable does this /* create target slot for UPDATE SET projection */ tupDesc = ExecTypeFromTL((List *) node->onConflictSet, relationDesc->tdhasoid); resultRelInfo->ri_onConflictProjSlot = ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc); /* build UPDATE SET projection state */ resultRelInfo->ri_onConflictSetProj = ExecBuildProjectionInfo(node->onConflictSet, econtext, resultRelInfo->ri_onConflictProjSlot, &mtstate->ps, relationDesc); and then ExecOnConflictUpdate can simply do this: /* Project the new tuple version */ ExecProject(resultRelInfo->ri_onConflictSetProj); /* Execute UPDATE with projection */ *returning = ExecUpdate(mtstate, &tuple.t_self, NULL, resultRelInfo->ri_onConflictProjSlot, planSlot, &mtstate->mt_epqstate, mtstate->ps.state, canSetTag); Now, maybe there is some reason I'm missing for the on conflict slot for the projection to be in ModifyTableState rather than resultRelInfo. But this code passes all current tests, so I don't know what that reason would be. Overall, the resulting code looks simpler to me than the previous arrangements. -- Álvaro Herrera https://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services