Received: from malur.postgresql.org ([2a02:16a8:dc51::56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1fH2Jb-0002TN-Qe for pgsql-hackers@arkaria.postgresql.org; Fri, 11 May 2018 07:18:08 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1fH2JX-0007jn-9E for pgsql-hackers@arkaria.postgresql.org; Fri, 11 May 2018 07:18:03 +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 1fH2JW-0007jd-Q6 for pgsql-hackers@lists.postgresql.org; Fri, 11 May 2018 07:18:03 +0000 Received: from mail-pg0-x234.google.com ([2607:f8b0:400e:c05::234]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1fH2JR-00075S-PA for pgsql-hackers@postgresql.org; Fri, 11 May 2018 07:18:01 +0000 Received: by mail-pg0-x234.google.com with SMTP id n1-v6so2068170pgs.2 for ; Fri, 11 May 2018 00:17:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enterprisedb-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=3v0jCWKb28Oo++OkNV6K4TQx45mhUgDpAmBx9WgEwwQ=; b=Ezdtv7MZeTAvgFGxYLQ4RKR9buEYBCQshecD2nFOMZvqdrtRx5Hsp1/BsEQ+J/sI+N 1ukWpHaCPuv2GzjzohDcKgscKy0E94m+s5Rz4SobEOyPJDRVpz85miawL2+BffNnWam4 7NFUDDLfE1nmpITBTKxx/bRwWuPe2XgWdyyw4CtcVBZGqwmt4hd+PidL1IFSftnhN3vw 5gUY2cdEcg0AMFW2n+4HLMDzI+uvVYnlCXVKy08kUMAGMYC2MEMdJclmdUiCQXdRO73U 2nC9u0m1UyD10tTQ19SaaPfYi2fk+SE7IwDh2nOVNsGwxaAAqK0XqoSxPbJFRHGgjm01 kA9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=3v0jCWKb28Oo++OkNV6K4TQx45mhUgDpAmBx9WgEwwQ=; b=qI9zOX01BJ4xNeIeHnN2YBmwn3uT3nGE1hK2YQWDhyU9rBqhqAR1JX0DykK029AuBG ux6/aeGHOlKJfYysy8x9QZqXzfrClHmiGY7mZoJZwi/CiClD0RWd0DDjc9EfTw82ug6k N2TadgQ6ugBRtRXQBbHgOL9ijiZzJNu2Gzdd/Q0f1RoShTsG+TbIHynlzsP5V8szOTM9 rDXWrlTEMQiDbNBM2FjuM0F5PLYhMhU40nxzszgy8w50gNhBYJ0tNpB6xcRo213T/0o4 FS3oHV3Jmpn8JYwQO1fUPS5FNN/nmCGimK+RdISB4miP6eTAHgxxJc9JTAt7tM4K+2rf cPRw== X-Gm-Message-State: ALKqPwdIFoPn725WReUOqLeTWTC0nBxmwqldVsTMCLvWBEPNmyc10EJQ 42l1eL+gooYsZmeVR7j2P6NrlWjyzcWyeE+kfKkaWw== X-Google-Smtp-Source: AB8JxZrqvKIB+F3ZEzHkh+TIaFMZTK4duQK76tCXZ8/rYQj7xfmHhf5fO+F80nmcPCLubr9a8/Afulgh1lI72Ah8cQk= X-Received: by 2002:a62:d97:: with SMTP id 23-v6mr4397911pfn.231.1526023076355; Fri, 11 May 2018 00:17:56 -0700 (PDT) MIME-Version: 1.0 Received: by 10.100.138.194 with HTTP; Fri, 11 May 2018 00:17:55 -0700 (PDT) In-Reply-To: <5AF440C2.3040805@lab.ntt.co.jp> References: <5AD5B1E0.8020404@lab.ntt.co.jp> <5AD5C5A1.1070509@lab.ntt.co.jp> <5ADF12D1.1030406@lab.ntt.co.jp> <5AE1C0D3.5060009@lab.ntt.co.jp> <5AE84FBF.3040905@lab.ntt.co.jp> <5AF2E09F.9060208@lab.ntt.co.jp> <5AF440C2.3040805@lab.ntt.co.jp> From: Ashutosh Bapat Date: Fri, 11 May 2018 12:47:55 +0530 Message-ID: Subject: Re: Expression errors with "FOR UPDATE" and postgres_fdw with partition wise join enabled. To: Etsuro Fujita Cc: Rajkumar Raghuwanshi , pgsql-hackers Content-Type: multipart/mixed; boundary="00000000000062d8bf056be8eff3" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --00000000000062d8bf056be8eff3 Content-Type: text/plain; charset="UTF-8" On Thu, May 10, 2018 at 6:23 PM, Etsuro Fujita wrote: > (2018/05/10 13:04), Ashutosh Bapat wrote: >> >> On Wed, May 9, 2018 at 5:20 PM, Etsuro Fujita >> wrote: >>> >>> (2018/04/25 18:51), Ashutosh Bapat wrote: >>>> >>>> Actually I noticed that ConvertRowtypeExpr are used to cast a child's >>>> whole row reference expression (not just a Var node) into that of its >>>> parent and not. For example a cast like NULL::child::parent produces a >>>> ConvertRowtypeExpr encapsulating a NULL constant node and not a Var >>>> node. We are interested only in ConvertRowtypeExprs embedding Var >>>> nodes with Var::varattno = 0. I have changed this code to use function >>>> is_converted_whole_row_reference() instead of the above code with >>>> Assert. In order to use that function, I had to take it out of >>>> setrefs.c and put it in nodeFuncs.c which seemed to be a better fit. >>> >>> >>> This change seems a bit confusing to me because the flag bits >>> "PVC_INCLUDE_CONVERTROWTYPES" and "PVC_RECURSE_CONVERTROWTYPES" passed to >>> pull_var_clause look as if it handles any ConvertRowtypeExpr nodes from a >>> given clause, but really, it only handles ConvertRowtypeExprs you >>> mentioned >>> above. To make that function easy to understand and use, I think it'd be >>> better to use the IsA(node, ConvertRowtypeExpr) test as in the first >>> version >>> of the patch, instead of is_converted_whole_row_reference, which would be >>> more consistent with other cases such as PlaceHolderVar. >> >> >> I agree that using is_converted_whole_row_reference() is not >> consistent with the other nodes that are handled by pull_var_clause(). >> I also agree that PVC_*_CONVERTROWTYPES doesn't reflect exactly what's >> being done with those options. But using >> is_converted_whole_row_reference() is the correct thing to do since we >> are interested only in the whole-row references embedded in >> ConvertRowtypeExpr. There can be anything encapsulated in >> ConvertRowtypeExpr(), a non-shippable function for example. We don't >> want to try to push that down in postgres_fdw's case. Neither in other >> cases. > > > Yeah, but I think the IsA test would be sufficient to make things work > correctly because we can assume that there aren't any other nodes than Var, > PHV, and CRE translating a wholerow value of a child table into a wholerow > value of its parent table's rowtype in the expression clause to which we > apply pull_var_clause with PVC_INCLUDE_CONVERTROWTYPES. Not really. Consider following case using the same tables fprt1 and fprt2 in test sql/postgres_fdw.sql create function row_as_is(a ftprt2_p1) returns ftprt2_p1 as $$begin return a; end;$$ language plpgsql; With the change you propose i.e. diff --git a/src/backend/optimizer/util/var.c b/src/backend/optimizer/util/var.c index f972712..088da14 100644 --- a/src/backend/optimizer/util/var.c +++ b/src/backend/optimizer/util/var.c @@ -646,8 +646,9 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context) else elog(ERROR, "PlaceHolderVar found where not expected"); } - else if (is_converted_whole_row_reference(node)) + else if (IsA(node, ConvertRowtypeExpr)) { + Assert(is_converted_whole_row_reference(node)); if (context->flags & PVC_INCLUDE_CONVERTROWTYPES) { context->varlist = lappend(context->varlist, node); following query crashes at Assert(is_converted_whole_row_reference(node)); If we remove that assert, it would end up pushing down row_as_is(), which is a local user defined function, to the foreign server. That's not desirable since the foreign server may not have that user defined function. > > BTW, one thing I noticed about the new version of the patch is: there is yet > another case where pull_var_clause produces an error. Here is an example: > > postgres=# create table t1 (a int, b text); > CREATE TABLE > postgres=# create table t2 (a int, b text); > CREATE TABLE > postgres=# create foreign table ft1 (a int, b text) server loopback options > (table_name 't1'); > CREATE FOREIGN TABLE > postgres=# create foreign table ft2 (a int, b text) server loopback options > (table_name 't2'); > CREATE FOREIGN TABLE > postgres=# insert into ft1 values (1, 'foo'); > INSERT 0 1 > postgres=# insert into ft1 values (2, 'bar'); > INSERT 0 1 > postgres=# insert into ft2 values (1, 'test1'); > INSERT 0 1 > postgres=# insert into ft2 values (2, 'test2'); > INSERT 0 1 > postgres=# analyze ft1; > ANALYZE > postgres=# analyze ft2; > ANALYZE > postgres=# create table parent (a int, b text); > CREATE TABLE > postgres=# alter foreign table ft1 inherit parent; > ALTER FOREIGN TABLE > postgres=# explain verbose update parent set b = ft2.b from ft2 where > parent.a = ft2.a returning parent; > ERROR: ConvertRowtypeExpr found where not expected > > To produce this, apply the patch in [1] as well as the new version; without > that patch in [1], the update query would crash the server (see [1] for > details). To fix this, I think we need to pass PVC_RECURSE_CONVERTROWTYPES > to pull_var_clause in build_remote_returning in postgres_fdw.c as well. I missed that call to PVC since it was added after I had created my patches. That's a disadvantage of having changed PVC to use flags instead of bools. We won't notice such changes. Thanks for pointing it out. Changed as per your suggestion. -- Best Wishes, Ashutosh Bapat EnterpriseDB Corporation The Postgres Database Company --00000000000062d8bf056be8eff3 Content-Type: application/x-gzip; name="expr_ref_error_pwj_v6.tar.gz" Content-Disposition: attachment; filename="expr_ref_error_pwj_v6.tar.gz" Content-Transfer-Encoding: base64 X-Attachment-Id: f_jh1mqfke0 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 fA6fw+fwOXwOn/t9/g293WczAMgAAA== --00000000000062d8bf056be8eff3--