Re: [HACKERS] Postgres_fdw behaves oddly

2017-02-07 Thread Yugo Nagata
Hi,

On Fri, 3 Feb 2017 18:12:01 +0900
vinayak  wrote:

> Hello,
> 
> I have tested some scenarios of inserting data into two foreign tables 
> using postgres_fdw. All the test cases works fine except Test 5.
> 
> In Test 5, I am expecting error as both the rows violates the 
> constraint. But at the COMMIT time transaction does not give any error 
> and it takes lock waiting for a transaction to finish.

I can reproduce this with REL9_6_STABLE.

The local process (application_name = psql) is waiting 
"COMMIT TRANSACTION" for returning at pgfdw_xact_callback()
 (in postgres_fdw/connection.c), and the remote process
(application_name = postgres_fdw) is stuck at _bt_doinsert()
with XactLockTableWait.

I attached the backtrace results.

I can't figure out yet why _bt_check_unique() returns without
calling ereport().

Regards,

> 
> Please check the below tests:
> 
> postgres=# CREATE SERVER loopback1 FOREIGN DATA WRAPPER POSTGRES_FDW 
> OPTIONS (dbname 'postgres');
> CREATE SERVER
> postgres=# CREATE SERVER loopback2 FOREIGN DATA WRAPPER POSTGRES_FDW 
> OPTIONS (dbname 'postgres');
> CREATE SERVER
> postgres=# CREATE USER MAPPING FOR CURRENT_USER SERVER loopback1;
> CREATE USER MAPPING
> postgres=# CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2;
> CREATE USER MAPPING
> 
> -- Here local table is created to refer as foreign table. The table has 
> constraints which are deferred till end of transaction.
> -- This allows COMMIT time errors to occur by inserting data which 
> violates constraints.
> 
> postgres=# *CREATE TABLE lt(val int UNIQUE DEFERRABLE INITIALLY DEFERRED);*
> CREATE TABLE
> postgres=# CREATE FOREIGN TABLE ft1_lt (val int) SERVER loopback1 
> OPTIONS (table_name 'lt');
> CREATE FOREIGN TABLE
> postgres=# CREATE FOREIGN TABLE ft2_lt (val int) SERVER loopback2 
> OPTIONS (table_name 'lt');
> CREATE FOREIGN TABLE
> 
> *Test 1: **
> **===*
> In a transaction insert two rows one each to the two foreign tables and 
> it works fine.
> 
> postgres=# BEGIN;
> BEGIN
> postgres=# INSERT INTO ft1_lt VALUES (1);
> INSERT 0 1
> postgres=# INSERT INTO ft2_lt VALUES (3);
> INSERT 0 1
> postgres=# COMMIT;
> COMMIT
> postgres=# SELECT * FROM lt;
>   val
> -
> 1
> 3
> (2 rows)
> 
> *Test 2:**
> **===*
> In a transaction insert two rows one each to the two foreign tables.
> One of the rows violates the constraint and other not. At the time of 
> COMMIT one of the foreign server violates the constraints so it return 
> error. I think this is also expected behavior.
> postgres=# BEGIN;
> BEGIN
> postgres=# INSERT INTO ft1_lt VALUES (1); -- Violates constraint
> INSERT 0 1
> postgres=# INSERT INTO ft2_lt VALUES (4);
> INSERT 0 1
> postgres=# COMMIT;
> 2017-02-03 15:26:28.667 JST [3081] ERROR:  duplicate key value violates 
> unique constraint "lt_val_key"
> 2017-02-03 15:26:28.667 JST [3081] DETAIL:  Key (val)=(1) already exists.
> 2017-02-03 15:26:28.667 JST [3081] STATEMENT:  COMMIT TRANSACTION
> 2017-02-03 15:26:28.668 JST [3075] ERROR:  duplicate key value violates 
> unique constraint "lt_val_key"
> 2017-02-03 15:26:28.668 JST [3075] DETAIL:  Key (val)=(1) already exists.
> 2017-02-03 15:26:28.668 JST [3075] CONTEXT:  Remote SQL command: COMMIT 
> TRANSACTION
> 2017-02-03 15:26:28.668 JST [3075] STATEMENT:  COMMIT;
> 2017-02-03 15:26:28.668 JST [3081] WARNING:  there is no transaction in 
> progress
> WARNING:  there is no transaction in progress
> ERROR:  duplicate key value violates unique constraint "lt_val_key"
> DETAIL:  Key (val)=(1) already exists.
> CONTEXT:  Remote SQL command: COMMIT TRANSACTION
> postgres=#
> postgres=#
> postgres=# SELECT * FROM lt;
>   val
> -
> 1
> 3
> (2 rows)
> 
> *Test 3:**
> **===*
> In a transaction insert two rows one each to the two foreign tables.
> One of the rows violates the constraint and other not. At the time of 
> COMMIT one of the foreign server violates the constraints so it return 
> error. I think this is also expected behavior.
> postgres=# BEGIN;
> BEGIN
> postgres=# INSERT INTO ft1_lt VALUES (4);
> INSERT 0 1
> postgres=# INSERT INTO ft2_lt VALUES (3); -- Violates constraint
> INSERT 0 1
> postgres=# COMMIT;
> 2017-02-03 15:27:14.331 JST [3084] ERROR:  duplicate key value violates 
> unique constraint "lt_val_key"
> 2017-02-03 15:27:14.331 JST [3084] DETAIL:  Key (val)=(3) already exists.
> 2017-02-03 15:27:14.331 JST [3084] STATEMENT:  COMMIT TRANSACTION
> 2017-02-03 15:27:14.332 JST [3075] ERROR:  duplicate key value violates 
> unique constraint "lt_val_key"
> 2017-02-03 15:27:14.332 JST [3075] DETAIL:  Key (val)=(3) already exists.
> 2017-02-03 15:27:14.332 JST [3075] CONTEXT:  Remote SQL command: COMMIT 
> TRANSACTION
> 2017-02-03 15:27:14.332 JST [3075] STATEMENT:  COMMIT;
> 2017-02-03 15:27:14.332 JST [3084] WARNING:  there is no transaction in 
> progress
> WARNING:  there is no transaction in progress
> ERROR:  duplicate key value violates unique constraint "lt_val_key"
> 

[HACKERS] Postgres_fdw behaves oddly

2017-02-03 Thread vinayak

Hello,

I have tested some scenarios of inserting data into two foreign tables 
using postgres_fdw. All the test cases works fine except Test 5.


In Test 5, I am expecting error as both the rows violates the 
constraint. But at the COMMIT time transaction does not give any error 
and it takes lock waiting for a transaction to finish.


Please check the below tests:

postgres=# CREATE SERVER loopback1 FOREIGN DATA WRAPPER POSTGRES_FDW 
OPTIONS (dbname 'postgres');

CREATE SERVER
postgres=# CREATE SERVER loopback2 FOREIGN DATA WRAPPER POSTGRES_FDW 
OPTIONS (dbname 'postgres');

CREATE SERVER
postgres=# CREATE USER MAPPING FOR CURRENT_USER SERVER loopback1;
CREATE USER MAPPING
postgres=# CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2;
CREATE USER MAPPING

-- Here local table is created to refer as foreign table. The table has 
constraints which are deferred till end of transaction.
-- This allows COMMIT time errors to occur by inserting data which 
violates constraints.


postgres=# *CREATE TABLE lt(val int UNIQUE DEFERRABLE INITIALLY DEFERRED);*
CREATE TABLE
postgres=# CREATE FOREIGN TABLE ft1_lt (val int) SERVER loopback1 
OPTIONS (table_name 'lt');

CREATE FOREIGN TABLE
postgres=# CREATE FOREIGN TABLE ft2_lt (val int) SERVER loopback2 
OPTIONS (table_name 'lt');

CREATE FOREIGN TABLE

*Test 1: **
**===*
In a transaction insert two rows one each to the two foreign tables and 
it works fine.


postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO ft1_lt VALUES (1);
INSERT 0 1
postgres=# INSERT INTO ft2_lt VALUES (3);
INSERT 0 1
postgres=# COMMIT;
COMMIT
postgres=# SELECT * FROM lt;
 val
-
   1
   3
(2 rows)

*Test 2:**
**===*
In a transaction insert two rows one each to the two foreign tables.
One of the rows violates the constraint and other not. At the time of 
COMMIT one of the foreign server violates the constraints so it return 
error. I think this is also expected behavior.

postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO ft1_lt VALUES (1); -- Violates constraint
INSERT 0 1
postgres=# INSERT INTO ft2_lt VALUES (4);
INSERT 0 1
postgres=# COMMIT;
2017-02-03 15:26:28.667 JST [3081] ERROR:  duplicate key value violates 
unique constraint "lt_val_key"

2017-02-03 15:26:28.667 JST [3081] DETAIL:  Key (val)=(1) already exists.
2017-02-03 15:26:28.667 JST [3081] STATEMENT:  COMMIT TRANSACTION
2017-02-03 15:26:28.668 JST [3075] ERROR:  duplicate key value violates 
unique constraint "lt_val_key"

2017-02-03 15:26:28.668 JST [3075] DETAIL:  Key (val)=(1) already exists.
2017-02-03 15:26:28.668 JST [3075] CONTEXT:  Remote SQL command: COMMIT 
TRANSACTION

2017-02-03 15:26:28.668 JST [3075] STATEMENT:  COMMIT;
2017-02-03 15:26:28.668 JST [3081] WARNING:  there is no transaction in 
progress

WARNING:  there is no transaction in progress
ERROR:  duplicate key value violates unique constraint "lt_val_key"
DETAIL:  Key (val)=(1) already exists.
CONTEXT:  Remote SQL command: COMMIT TRANSACTION
postgres=#
postgres=#
postgres=# SELECT * FROM lt;
 val
-
   1
   3
(2 rows)

*Test 3:**
**===*
In a transaction insert two rows one each to the two foreign tables.
One of the rows violates the constraint and other not. At the time of 
COMMIT one of the foreign server violates the constraints so it return 
error. I think this is also expected behavior.

postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO ft1_lt VALUES (4);
INSERT 0 1
postgres=# INSERT INTO ft2_lt VALUES (3); -- Violates constraint
INSERT 0 1
postgres=# COMMIT;
2017-02-03 15:27:14.331 JST [3084] ERROR:  duplicate key value violates 
unique constraint "lt_val_key"

2017-02-03 15:27:14.331 JST [3084] DETAIL:  Key (val)=(3) already exists.
2017-02-03 15:27:14.331 JST [3084] STATEMENT:  COMMIT TRANSACTION
2017-02-03 15:27:14.332 JST [3075] ERROR:  duplicate key value violates 
unique constraint "lt_val_key"

2017-02-03 15:27:14.332 JST [3075] DETAIL:  Key (val)=(3) already exists.
2017-02-03 15:27:14.332 JST [3075] CONTEXT:  Remote SQL command: COMMIT 
TRANSACTION

2017-02-03 15:27:14.332 JST [3075] STATEMENT:  COMMIT;
2017-02-03 15:27:14.332 JST [3084] WARNING:  there is no transaction in 
progress

WARNING:  there is no transaction in progress
ERROR:  duplicate key value violates unique constraint "lt_val_key"
DETAIL:  Key (val)=(3) already exists.
CONTEXT:  Remote SQL command: COMMIT TRANSACTION
postgres=# SELECT * FROM lt;
 val
-
   1
   3
   4
(3 rows)
*Test 4:**
**===*
In a transaction insert two rows one each to the two foreign tables.
Both the rows violates the constraint. So at the time of COMMIT it 
returns error. I think this is also expected behavior.


postgres=# BEGIN;
BEGIN
postgres=# INSERT INTO ft1_lt VALUES (1); -- Violates constraint
INSERT 0 1
postgres=# INSERT INTO ft2_lt VALUES (3); -- Violates constraint
INSERT 0 1
postgres=# COMMIT;
2017-02-03 15:29:18.857 JST [3081] ERROR:  duplicate key value violates 
unique constraint "lt_val_key"

2017-02-03 15:29:18.857 JST [3081] DETAIL:  Key (val)=(1) already exists.
2017-02-03 

Re: [HACKERS] postgres_fdw behaves oddly

2014-11-24 Thread Etsuro Fujita
(2014/11/23 6:16), Tom Lane wrote:
 I committed this with some cosmetic adjustments, and one not-so-cosmetic
 one:

Thanks for improving and committing the patch!

Best regards,
Etsuro Fujita


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-23 Thread Ashutosh Bapat
On Sun, Nov 23, 2014 at 2:46 AM, Tom Lane t...@sss.pgh.pa.us wrote:

 Etsuro Fujita fujita.ets...@lab.ntt.co.jp writes:
  (2014/11/19 18:21), Ashutosh Bapat wrote:
  Ok. I added that comment to the commitfest and changed the status to
  ready for commiter.

  Many thanks!

 I committed this with some cosmetic adjustments, and one not-so-cosmetic
 one: I left it continuing to allow CTID conditions to be sent to the
 remote server.  That works today and we shouldn't disable it, especially
 not in the back branches where it could mean a performance regression
 in a minor release.


Thanks.


 As for the question of whether reltargetlist or tlist should be examined,
 reltargetlist is the correct thing.  I do not see a need to modify
 use_physical_tlist either.  If you trace through what happens in e.g.
 postgres_fdw, you'll notice that it only bothers to retrieve actually-used
 columns (which it computes correctly) from the remote side.  It then
 constructs a scan tuple that corresponds to the foreign table's physical
 column set, inserting NULLs for any unfetched columns.  This is handed
 back to execScan.c and matches what a heapscan or indexscan would produce.
 The point of the use_physical_tlist optimization is to avoid a projection
 step *on this tuple* if we don't really need to do one (ie, if it'd be
 just as good for the scan node's output tuple to be identical to the row's
 physical tuple).  If we disabled use_physical_tlist then we'd be forcing
 a projection step that would have the effect of removing the NULLs for
 unfetched columns, but it would not actually be of value, just as it isn't
 in the corresponding cases for heap/index scans.

 For the current patch, that's fair.

In grouping_planner() the targetlist of the topmost plan node of join tree
is changed to the set of expressions requested in the query.
1554 else
1555 {
1556 /*
1557  * Otherwise, just replace the subplan's flat
tlist with
1558  * the desired tlist.
1559  */
1560 result_plan-targetlist = sub_tlist;
1561 }
This means that for a simple SELECT from the foreign table, projection
would be necessary in ExecScan if all the columns are not required.

So, the strategy to emulate heap or index scan wastes extra cycles and
memory in adding NULL columns which are not required and then filtering
them during the projection (within ExecScan itself). It also limits the
ability of foreign scans to fetch shippable expressions when those
expressions are part of the targetlist and fetching their values (instead
of the columns participating in the expressions) reduces the size of the
fetched row.

These cases do not exist for heap scans or index scans because the tuples
are obtained directly from the buffer, so no extra memory required for the
extra columns and projection as well as expression evaluation is anyway
required.


BTW, given that there wasn't any very good way to test the createplan.c
 fix except by adding test cases to postgres_fdw, I didn't see much value
 in splitting the patch in two.  The committed patch includes tests that
 the createplan.c bug is fixed as well as the postgres_fdw one.

 regards, tom lane




-- 
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-22 Thread Tom Lane
Etsuro Fujita fujita.ets...@lab.ntt.co.jp writes:
 (2014/11/19 18:21), Ashutosh Bapat wrote:
 Ok. I added that comment to the commitfest and changed the status to
 ready for commiter.

 Many thanks!

I committed this with some cosmetic adjustments, and one not-so-cosmetic
one: I left it continuing to allow CTID conditions to be sent to the
remote server.  That works today and we shouldn't disable it, especially
not in the back branches where it could mean a performance regression
in a minor release.

As for the question of whether reltargetlist or tlist should be examined,
reltargetlist is the correct thing.  I do not see a need to modify
use_physical_tlist either.  If you trace through what happens in e.g.
postgres_fdw, you'll notice that it only bothers to retrieve actually-used
columns (which it computes correctly) from the remote side.  It then
constructs a scan tuple that corresponds to the foreign table's physical
column set, inserting NULLs for any unfetched columns.  This is handed
back to execScan.c and matches what a heapscan or indexscan would produce.
The point of the use_physical_tlist optimization is to avoid a projection
step *on this tuple* if we don't really need to do one (ie, if it'd be
just as good for the scan node's output tuple to be identical to the row's
physical tuple).  If we disabled use_physical_tlist then we'd be forcing
a projection step that would have the effect of removing the NULLs for
unfetched columns, but it would not actually be of value, just as it isn't
in the corresponding cases for heap/index scans.

BTW, given that there wasn't any very good way to test the createplan.c
fix except by adding test cases to postgres_fdw, I didn't see much value
in splitting the patch in two.  The committed patch includes tests that
the createplan.c bug is fixed as well as the postgres_fdw one.

regards, tom lane


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-19 Thread Ashutosh Bapat
Ok. I added that comment to the commitfest and changed the status to ready
for commiter.

On Wed, Nov 19, 2014 at 1:10 PM, Etsuro Fujita fujita.ets...@lab.ntt.co.jp
wrote:

 (2014/11/19 15:56), Ashutosh Bapat wrote:

 On Wed, Nov 19, 2014 at 12:14 PM, Etsuro Fujita
 fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
 (2014/11/19 14:58), Ashutosh Bapat wrote:


  May be we should modify use_physical_tlist() to return
 false in
 case of RELKIND_FOREIGN_TABLE, so that we can use tlist in
 create_foreignscan_plan(). I do not see any create_*_plan()
 function
 using reltargetlist directly.


  Yeah, I think we can do that, but I'm not sure that we should use
 tlist in create_foreignscan_plan(), not rel-reltargetlist.  How
 about leaving this for committers to decide.


  I am fine with that. May be you want to add an XXX comment there to
 bring it to the committer's notice.


 It's ok, but I'm not convinced with your idea.  So, I think the comment
 can be adequately described by you, not by me.  So, my proposal is for you
 to add the comment to the CF app.  Could you do that?


 Thanks,

 Best regards,
 Etsuro Fujita




-- 
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-19 Thread Etsuro Fujita

(2014/11/19 18:21), Ashutosh Bapat wrote:

Ok. I added that comment to the commitfest and changed the status to
ready for commiter.


Many thanks!

PS: the link to the review emails that discuss the issue doesn't work 
properly, so I re-added the link.


Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/17 19:36), Ashutosh Bapat wrote:

Here are my comments about the patch fscan_reltargetlist.patch


Thanks for the review!


1. This isn't your change, but we might be able to get rid of assignment
2071 /* Are any system columns requested from rel? */
2072 scan_plan-fsSystemCol = false;

since make_foreignscan() already does that. But I will leave upto you to
remove this assignment or not.


As you pointed out, the assignment is redundant, but I think that that'd 
improve the clarity and readability.  So, I'd vote for leaving that as is.



2. Instead of using rel-reltargetlist, we should use the tlist passed
by caller. This is the tlist expected from the Plan node. For foreign
scans it will be same as rel-reltargetlist. Using tlist would make the
function consistent with create_*scan_plan functions.


I disagree with that for the reasons mentioned below:

* For a foreign scan, tlist is *not* necessarily the same as 
rel-reltargetlist (ie, there is a case where tlist contains all user 
attributes while rel-reltargetlist contains only attributes actually 
needed by the query).  In such a case it'd be inefficient to use tlist 
rather than rel-reltargetlist.


* I think that it'd improve the readability to match the code with other 
places that execute similar processing, such as check_index_only() and 
remove_unused_subquery_outputs().


Thanks,

Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/17 19:54), Ashutosh Bapat wrote:

Here are comments for postgres_fdw-syscol patch.


Thanks for the review!


Code
---
1. Instead of a single liner comment System columns can't be sent to
remote., it might be better to explain why system columns can't be sent
to the remote.


Done.


2. The comment in deparseVar is single line comment, so it should start
and end on the same line i.e. /* and */ should be on the same line.


Done.


3. Since there is already a testcase which triggered this particular
change, it will good, if we add that to regression in postgres_fdw.


Done.

Please find attached an updated version of the patch.

Thanks,

Best regards,
Etsuro Fujita
*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***
*** 253,258  foreign_expr_walker(Node *node,
--- 253,268 
  if (var-varno == glob_cxt-foreignrel-relid 
  	var-varlevelsup == 0)
  {
+ 	/*
+ 	 * System columns can't be sent to remote since the values
+ 	 * for system columns might be different between local and
+ 	 * remote.
+ 	 *
+ 	 * XXX: we should probably send ctid to remote.
+ 	 */
+ 	if (var-varattno  0)
+ 		return false;
+ 
  	/* Var belongs to foreign table */
  	collation = var-varcollid;
  	state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
***
*** 1262,1267  deparseVar(Var *node, deparse_expr_cxt *context)
--- 1272,1280 
  	if (node-varno == context-foreignrel-relid 
  		node-varlevelsup == 0)
  	{
+ 		/* Var shouldn't be a system column */
+ 		Assert(node-varattno = 0);
+ 
  		/* Var belongs to foreign table */
  		deparseColumnRef(buf, node-varno, node-varattno, context-root);
  	}
*** a/contrib/postgres_fdw/expected/postgres_fdw.out
--- b/contrib/postgres_fdw/expected/postgres_fdw.out
***
*** 353,358  EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
--- 353,368 
 Remote SQL: SELECT C 1, c2, c3, c4, c5, c6, c7, c8 FROM S 1.T 1 WHERE ((C 1 = c2))
  (3 rows)
  
+ -- where with system column conditions
+ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.tableoid != 0;
+QUERY PLAN
+ -
+  Foreign Scan on public.ft1 t1
+Output: c1, c2, c3, c4, c5, c6, c7, c8
+Filter: (t1.tableoid  0::oid)
+Remote SQL: SELECT C 1, c2, c3, c4, c5, c6, c7, c8 FROM S 1.T 1
+ (4 rows)
+ 
  -- ===
  -- WHERE with remotely-executable conditions
  -- ===
*** a/contrib/postgres_fdw/sql/postgres_fdw.sql
--- b/contrib/postgres_fdw/sql/postgres_fdw.sql
***
*** 180,185  EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = postgres_fdw_a
--- 180,187 
  EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2;
  EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
  EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
+ -- where with system column conditions
+ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE t1.tableoid != 0;
  
  -- ===
  -- WHERE with remotely-executable conditions

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/18 18:27), Ashutosh Bapat wrote:

On Tue, Nov 18, 2014 at 1:50 PM, Etsuro Fujita
fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
(2014/11/17 19:36), Ashutosh Bapat wrote:



Here are my comments about the patch fscan_reltargetlist.patch



2. Instead of using rel-reltargetlist, we should use the tlist
passed
by caller. This is the tlist expected from the Plan node. For
foreign
scans it will be same as rel-reltargetlist. Using tlist would
make the
function consistent with create_*scan_plan functions.



I disagree with that for the reasons mentioned below:

* For a foreign scan, tlist is *not* necessarily the same as
rel-reltargetlist (ie, there is a case where tlist contains all
user attributes while rel-reltargetlist contains only attributes
actually needed by the query).  In such a case it'd be inefficient
to use tlist rather than rel-reltargetlist.



create_foreignscan_plan() is called from create_scan_plan(), which
passes the tlist. The later uses function use_physical_tlist() to decide
which targetlist should be used (physical or actual). As per code below
in this function

  485 /*
  486  * We can do this for real relation scans, subquery scans,
function scans,
  487  * values scans, and CTE scans (but not for, eg, joins).
  488  */
  489 if (rel-rtekind != RTE_RELATION 
  490 rel-rtekind != RTE_SUBQUERY 
  491 rel-rtekind != RTE_FUNCTION 
  492 rel-rtekind != RTE_VALUES 
  493 rel-rtekind != RTE_CTE)
  494 return false;
  495
  496 /*
  497  * Can't do it with inheritance cases either (mainly because
Append
  498  * doesn't project).
  499  */
  500 if (rel-reloptkind != RELOPT_BASEREL)
  501 return false;

For foreign tables as well as the tables under inheritance hierarchy it
uses the actual targetlist, which contains only the required columns IOW
rel-reltargetlist (see build_path_tlist()) with nested loop parameters
substituted. So, it never included unnecessary columns in the
targetlist.


Maybe I'm missing something, but I think you are overlooking the case 
for foreign tables that are *not* under an inheritance hierarchy.  (Note 
that the rtekind for foreign tables is RTE_RELATION.)


Thanks,

Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/18 18:37), Ashutosh Bapat wrote:

On Tue, Nov 18, 2014 at 1:55 PM, Etsuro Fujita
fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
(2014/11/17 19:54), Ashutosh Bapat wrote:



Here are comments for postgres_fdw-syscol patch.



Code
---
1. Instead of a single liner comment System columns can't be
sent to
remote., it might be better to explain why system columns can't
be sent
to the remote.



Done.



I would add  and foreign values do not make sense locally (except may
be ctid clubbed with foreign server_id) to make it more clear. But I
will leave that for the commiter to decide.


OK.


3. Since there is already a testcase which triggered this particular
change, it will good, if we add that to regression in postgres_fdw.



Done.



I think, a better case would be SELECT * FROM ft1 t1, pg_class t2 WHERE
t1.tableoid = t2.oid. The condition makes sure that the tableoid in the
row is same as the OID of the foreign table recorded in pg_class
locally. And the EXPLAIN of the query which clearly shows that the
tableoid column in not fetched from the foreign server.


I thought that test, but I didn't use it because I think we can't see 
(at least from the EXPLAIN) why the qual is not pushed down: the qual 
isn't pushed down possibly becasue the qual is considered as a *join* 
qual, not because the qual just cotains tableoid.  (Having said that, I 
think we can see if the qual isn't pushed down as a join qual for a 
parameterized plan, but ISTM it's worth complicating regression tests.)



Once we resolve the other patch on this thread,  I think this item can
be marked as ready for commiter from my side.


OK.  Thank you for the review.

Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Ashutosh Bapat
On Wed, Nov 19, 2014 at 11:18 AM, Etsuro Fujita fujita.ets...@lab.ntt.co.jp
 wrote:

 (2014/11/18 18:27), Ashutosh Bapat wrote:

 On Tue, Nov 18, 2014 at 1:50 PM, Etsuro Fujita
 fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
 (2014/11/17 19:36), Ashutosh Bapat wrote:


  Here are my comments about the patch fscan_reltargetlist.patch


  2. Instead of using rel-reltargetlist, we should use the tlist
 passed
 by caller. This is the tlist expected from the Plan node. For
 foreign
 scans it will be same as rel-reltargetlist. Using tlist would
 make the
 function consistent with create_*scan_plan functions.


  I disagree with that for the reasons mentioned below:

 * For a foreign scan, tlist is *not* necessarily the same as
 rel-reltargetlist (ie, there is a case where tlist contains all
 user attributes while rel-reltargetlist contains only attributes
 actually needed by the query).  In such a case it'd be inefficient
 to use tlist rather than rel-reltargetlist.


  create_foreignscan_plan() is called from create_scan_plan(), which
 passes the tlist. The later uses function use_physical_tlist() to decide
 which targetlist should be used (physical or actual). As per code below
 in this function

   485 /*
   486  * We can do this for real relation scans, subquery scans,
 function scans,
   487  * values scans, and CTE scans (but not for, eg, joins).
   488  */
   489 if (rel-rtekind != RTE_RELATION 
   490 rel-rtekind != RTE_SUBQUERY 
   491 rel-rtekind != RTE_FUNCTION 
   492 rel-rtekind != RTE_VALUES 
   493 rel-rtekind != RTE_CTE)
   494 return false;
   495
   496 /*
   497  * Can't do it with inheritance cases either (mainly because
 Append
   498  * doesn't project).
   499  */
   500 if (rel-reloptkind != RELOPT_BASEREL)
   501 return false;

 For foreign tables as well as the tables under inheritance hierarchy it
 uses the actual targetlist, which contains only the required columns IOW
 rel-reltargetlist (see build_path_tlist()) with nested loop parameters
 substituted. So, it never included unnecessary columns in the
 targetlist.


 Maybe I'm missing something, but I think you are overlooking the case for
 foreign tables that are *not* under an inheritance hierarchy.  (Note that
 the rtekind for foreign tables is RTE_RELATION.)



Ah! you are right. I confused between rtekind and relkind. Sorry for that.
May be we should modify use_physical_tlist() to return false in case of
RELKIND_FOREIGN_TABLE, so that we can use tlist in
create_foreignscan_plan(). I do not see any create_*_plan() function using
reltargetlist directly.


 Thanks,

 Best regards,
 Etsuro Fujita




-- 
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/19 14:58), Ashutosh Bapat wrote:

On Wed, Nov 19, 2014 at 11:18 AM, Etsuro Fujita
fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
(2014/11/18 18:27), Ashutosh Bapat wrote:
On Tue, Nov 18, 2014 at 1:50 PM, Etsuro Fujita
fujita.ets...@lab.ntt.co.jp
 (2014/11/17 19:36), Ashutosh Bapat wrote:



 Here are my comments about the patch
fscan_reltargetlist.patch



 2. Instead of using rel-reltargetlist, we should use
the tlist
 passed
 by caller. This is the tlist expected from the Plan
node. For
 foreign
 scans it will be same as rel-reltargetlist. Using
tlist would
 make the
 function consistent with create_*scan_plan functions.



 I disagree with that for the reasons mentioned below:

 * For a foreign scan, tlist is *not* necessarily the same as
 rel-reltargetlist (ie, there is a case where tlist
contains all
 user attributes while rel-reltargetlist contains only
attributes
 actually needed by the query).  In such a case it'd be
inefficient
 to use tlist rather than rel-reltargetlist.



create_foreignscan_plan() is called from create_scan_plan(), which
passes the tlist. The later uses function use_physical_tlist()
to decide
which targetlist should be used (physical or actual). As per
code below
in this function

   485 /*
   486  * We can do this for real relation scans, subquery
scans,
function scans,
   487  * values scans, and CTE scans (but not for, eg, joins).
   488  */
   489 if (rel-rtekind != RTE_RELATION 
   490 rel-rtekind != RTE_SUBQUERY 
   491 rel-rtekind != RTE_FUNCTION 
   492 rel-rtekind != RTE_VALUES 
   493 rel-rtekind != RTE_CTE)
   494 return false;
   495
   496 /*
   497  * Can't do it with inheritance cases either (mainly
because
Append
   498  * doesn't project).
   499  */
   500 if (rel-reloptkind != RELOPT_BASEREL)
   501 return false;

For foreign tables as well as the tables under inheritance
hierarchy it
uses the actual targetlist, which contains only the required
columns IOW
rel-reltargetlist (see build_path_tlist()) with nested loop
parameters
substituted. So, it never included unnecessary columns in the
targetlist.



Maybe I'm missing something, but I think you are overlooking the
case for foreign tables that are *not* under an inheritance
hierarchy.  (Note that the rtekind for foreign tables is RTE_RELATION.)



Ah! you are right. I confused between rtekind and relkind. Sorry for
that. May be we should modify use_physical_tlist() to return false in
case of RELKIND_FOREIGN_TABLE, so that we can use tlist in
create_foreignscan_plan(). I do not see any create_*_plan() function
using reltargetlist directly.


Yeah, I think we can do that, but I'm not sure that we should use tlist 
in create_foreignscan_plan(), not rel-reltargetlist.  How about leaving 
this for committers to decide.


Thanks,

Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Ashutosh Bapat
On Wed, Nov 19, 2014 at 12:14 PM, Etsuro Fujita fujita.ets...@lab.ntt.co.jp
 wrote:

 (2014/11/19 14:58), Ashutosh Bapat wrote:

 On Wed, Nov 19, 2014 at 11:18 AM, Etsuro Fujita
 fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
 (2014/11/18 18:27), Ashutosh Bapat wrote:
 On Tue, Nov 18, 2014 at 1:50 PM, Etsuro Fujita
 fujita.ets...@lab.ntt.co.jp
  (2014/11/17 19:36), Ashutosh Bapat wrote:


   Here are my comments about the patch
 fscan_reltargetlist.patch


   2. Instead of using rel-reltargetlist, we should use
 the tlist
  passed
  by caller. This is the tlist expected from the Plan
 node. For
  foreign
  scans it will be same as rel-reltargetlist. Using
 tlist would
  make the
  function consistent with create_*scan_plan functions.


   I disagree with that for the reasons mentioned below:

  * For a foreign scan, tlist is *not* necessarily the same as
  rel-reltargetlist (ie, there is a case where tlist
 contains all
  user attributes while rel-reltargetlist contains only
 attributes
  actually needed by the query).  In such a case it'd be
 inefficient
  to use tlist rather than rel-reltargetlist.


  create_foreignscan_plan() is called from create_scan_plan(), which
 passes the tlist. The later uses function use_physical_tlist()
 to decide
 which targetlist should be used (physical or actual). As per
 code below
 in this function

485 /*
486  * We can do this for real relation scans, subquery
 scans,
 function scans,
487  * values scans, and CTE scans (but not for, eg,
 joins).
488  */
489 if (rel-rtekind != RTE_RELATION 
490 rel-rtekind != RTE_SUBQUERY 
491 rel-rtekind != RTE_FUNCTION 
492 rel-rtekind != RTE_VALUES 
493 rel-rtekind != RTE_CTE)
494 return false;
495
496 /*
497  * Can't do it with inheritance cases either (mainly
 because
 Append
498  * doesn't project).
499  */
500 if (rel-reloptkind != RELOPT_BASEREL)
501 return false;

 For foreign tables as well as the tables under inheritance
 hierarchy it
 uses the actual targetlist, which contains only the required
 columns IOW
 rel-reltargetlist (see build_path_tlist()) with nested loop
 parameters
 substituted. So, it never included unnecessary columns in the
 targetlist.


  Maybe I'm missing something, but I think you are overlooking the
 case for foreign tables that are *not* under an inheritance
 hierarchy.  (Note that the rtekind for foreign tables is
 RTE_RELATION.)


  Ah! you are right. I confused between rtekind and relkind. Sorry for
 that. May be we should modify use_physical_tlist() to return false in
 case of RELKIND_FOREIGN_TABLE, so that we can use tlist in
 create_foreignscan_plan(). I do not see any create_*_plan() function
 using reltargetlist directly.


 Yeah, I think we can do that, but I'm not sure that we should use tlist in
 create_foreignscan_plan(), not rel-reltargetlist.  How about leaving this
 for committers to decide.


I am fine with that. May be you want to add an XXX comment there to bring
it to the committer's notice.



 Thanks,

 Best regards,
 Etsuro Fujita




-- 
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/19 14:55), Etsuro Fujita wrote:

(2014/11/18 18:37), Ashutosh Bapat wrote:

On Tue, Nov 18, 2014 at 1:55 PM, Etsuro Fujita
fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
(2014/11/17 19:54), Ashutosh Bapat wrote:



Here are comments for postgres_fdw-syscol patch.



3. Since there is already a testcase which triggered this
particular
change, it will good, if we add that to regression in
postgres_fdw.



Done.



I think, a better case would be SELECT * FROM ft1 t1, pg_class t2 WHERE
t1.tableoid = t2.oid. The condition makes sure that the tableoid in the
row is same as the OID of the foreign table recorded in pg_class
locally. And the EXPLAIN of the query which clearly shows that the
tableoid column in not fetched from the foreign server.


I thought that test, but I didn't use it because I think we can't see
(at least from the EXPLAIN) why the qual is not pushed down: the qual
isn't pushed down possibly becasue the qual is considered as a *join*
qual, not because the qual just cotains tableoid.  (Having said that, I
think we can see if the qual isn't pushed down as a join qual for a
parameterized plan, but ISTM it's worth complicating regression tests.)


Sorry, I incorrectly wrote the last sentence.  What I tried to write is, 
ISTM it's *not* worth complicating regression tests.


Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-18 Thread Etsuro Fujita

(2014/11/19 15:56), Ashutosh Bapat wrote:

On Wed, Nov 19, 2014 at 12:14 PM, Etsuro Fujita
fujita.ets...@lab.ntt.co.jp mailto:fujita.ets...@lab.ntt.co.jp wrote:
(2014/11/19 14:58), Ashutosh Bapat wrote:



May be we should modify use_physical_tlist() to return
false in
case of RELKIND_FOREIGN_TABLE, so that we can use tlist in
create_foreignscan_plan(). I do not see any create_*_plan() function
using reltargetlist directly.



Yeah, I think we can do that, but I'm not sure that we should use
tlist in create_foreignscan_plan(), not rel-reltargetlist.  How
about leaving this for committers to decide.



I am fine with that. May be you want to add an XXX comment there to
bring it to the committer's notice.


It's ok, but I'm not convinced with your idea.  So, I think the comment 
can be adequately described by you, not by me.  So, my proposal is for 
you to add the comment to the CF app.  Could you do that?


Thanks,

Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-17 Thread Ashutosh Bapat
Hi Fujita-san,

Here are comments for postgres_fdw-syscol patch.

Sanity

The patch applies and compiles cleanly.
The server regression and regression in contrib/postgres_fdw,file_fdw run
cleanly.

Code
---
1. Instead of a single liner comment System columns can't be sent to
remote., it might be better to explain why system columns can't be sent to
the remote.
2. The comment in deparseVar is single line comment, so it should start and
end on the same line i.e. /* and */ should be on the same line.
3. Since there is already a testcase which triggered this particular
change, it will good, if we add that to regression in postgres_fdw.

On Mon, Nov 17, 2014 at 4:06 PM, Ashutosh Bapat 
ashutosh.ba...@enterprisedb.com wrote:

 Hi Fujita-san,

 Here are my comments about the patch fscan_reltargetlist.patch
 Sanity
 
 Patch applies and compiles cleanly.
 Regressions in test/regress folder and postgres_fdw and file_fdw are clean.

 1. This isn't your change, but we might be able to get rid of assignment
 2071 /* Are any system columns requested from rel? */
 2072 scan_plan-fsSystemCol = false;

 since make_foreignscan() already does that. But I will leave upto you to
 remove this assignment or not.

 2. Instead of using rel-reltargetlist, we should use the tlist passed by
 caller. This is the tlist expected from the Plan node. For foreign scans it
 will be same as rel-reltargetlist. Using tlist would make the function
 consistent with create_*scan_plan functions.

 Otherwise, the patch looks good.

 On Wed, Nov 12, 2014 at 12:55 PM, Etsuro Fujita 
 fujita.ets...@lab.ntt.co.jp wrote:

 (2014/11/11 18:45), Etsuro Fujita wrote:

 (2014/11/10 20:05), Ashutosh Bapat wrote:

 Since two separate issues 1. using reltargetlist instead of attr_needed
 and 2. system columns usage in FDW are being tackled here, we should
 separate the patch into two one for each of the issues.


 Agreed.  Will split the patch into two.


 Here are splitted patches:

 fscan-reltargetlist.patch  - patch for #1
 postgres_fdw-syscol.patch  - patch for #2


 Thanks,

 Best regards,
 Etsuro Fujita




 --
 Best Wishes,
 Ashutosh Bapat
 EnterpriseDB Corporation
 The Postgres Database Company




-- 
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-11 Thread Etsuro Fujita

Hi Ashutosh,

Thanks for the review!

(2014/11/10 20:05), Ashutosh Bapat wrote:

Since two separate issues 1. using reltargetlist instead of attr_needed
and 2. system columns usage in FDW are being tackled here, we should
separate the patch into two one for each of the issues.


Agreed.  Will split the patch into two.


While I agree that the system columns shouldn't be sent to the remote
node, it doesn't look clear to me as to what would they or their values
mean in the context of foreign data. Some columns like tableoid would
have a value which is the OID of the foreign table, other system columns
like xmin/xmax/ctid will have different meanings (or no meaning)
depending upon the foreign data source. In case of later columns, each
FDW would have its own way of defining that meaning (I guess). But in
any case, I agree that we shouldn't send the system columns to the
remote side.

Is there a way we can enforce this rule across all the FDWs? OR we want
to tackle it separately per FDW?


ISTM it'd be better to tackle it separately because I feel that such an 
enforcement by the PG core would go too far.  I'm also concerned about a 
possibility of impedance mismatching between such an enforcement and 
postgres_fdw, which sends the ctid column to the remote side internally 
when executing UPDATE/DELETE on foreign tables.  See 
postgresPlanForeignModify and eg, deparseUpdateSql.


Best regards,
Etsuro Fujita


--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-11 Thread Etsuro Fujita

(2014/11/11 18:45), Etsuro Fujita wrote:

(2014/11/10 20:05), Ashutosh Bapat wrote:

Since two separate issues 1. using reltargetlist instead of attr_needed
and 2. system columns usage in FDW are being tackled here, we should
separate the patch into two one for each of the issues.


Agreed.  Will split the patch into two.


Here are splitted patches:

fscan-reltargetlist.patch  - patch for #1
postgres_fdw-syscol.patch  - patch for #2

Thanks,

Best regards,
Etsuro Fujita
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
***
*** 20,25 
--- 20,26 
  #include math.h
  
  #include access/skey.h
+ #include access/sysattr.h
  #include catalog/pg_class.h
  #include foreign/fdwapi.h
  #include miscadmin.h
***
*** 1945,1950  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
--- 1946,1953 
  	RelOptInfo *rel = best_path-path.parent;
  	Index		scan_relid = rel-relid;
  	RangeTblEntry *rte;
+ 	Bitmapset  *attrs_used = NULL;
+ 	ListCell   *lc;
  	int			i;
  
  	/* it should be a base rel... */
***
*** 1993,2008  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (!bms_is_empty(rel-attr_needed[i - rel-min_attr]))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
  	return scan_plan;
  }
  
--- 1996,2030 
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
+ 
+ 	/*
+ 	 * Add all the attributes needed for joins or final output.  Note: we must
+ 	 * look at reltargetlist, not the attr_needed data, because attr_needed
+ 	 * isn't computed for inheritance child rels.
+ 	 */
+ 	pull_varattnos((Node *) rel-reltargetlist, rel-relid, attrs_used);
+ 
+ 	/* Add all the attributes used by restriction clauses. */
+ 	foreach(lc, rel-baserestrictinfo)
+ 	{
+ 		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ 
+ 		pull_varattnos((Node *) rinfo-clause, rel-relid, attrs_used);
+ 	}
+ 
+ 	/* Are any system columns requested from rel? */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, attrs_used))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
+ 	bms_free(attrs_used);
+ 
  	return scan_plan;
  }
  
*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***
*** 252,257  foreign_expr_walker(Node *node,
--- 252,265 
  if (var-varno == glob_cxt-foreignrel-relid 
  	var-varlevelsup == 0)
  {
+ 	/*
+ 	 * System columns can't be sent to remote.
+ 	 *
+ 	 * XXX: we should probably send ctid to remote.
+ 	 */
+ 	if (var-varattno  0)
+ 		return false;
+ 
  	/* Var belongs to foreign table */
  	collation = var-varcollid;
  	state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
***
*** 1261,1266  deparseVar(Var *node, deparse_expr_cxt *context)
--- 1269,1279 
  	if (node-varno == context-foreignrel-relid 
  		node-varlevelsup == 0)
  	{
+ 		/*
+ 		 * System columns shouldn't be examined here.
+ 		 */
+ 		Assert(node-varattno = 0);
+ 
  		/* Var belongs to foreign table */
  		deparseColumnRef(buf, node-varno, node-varattno, context-root);
  	}

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-11-10 Thread Ashutosh Bapat
Since two separate issues 1. using reltargetlist instead of attr_needed and
2. system columns usage in FDW are being tackled here, we should separate
the patch into two one for each of the issues.

While I agree that the system columns shouldn't be sent to the remote node,
it doesn't look clear to me as to what would they or their values mean in
the context of foreign data. Some columns like tableoid would have a value
which is the OID of the foreign table, other system columns like
xmin/xmax/ctid will have different meanings (or no meaning) depending upon
the foreign data source. In case of later columns, each FDW would have its
own way of defining that meaning (I guess). But in any case, I agree that
we shouldn't send the system columns to the remote side.

Is there a way we can enforce this rule across all the FDWs? OR we want to
tackle it separately per FDW?

On Tue, Oct 14, 2014 at 8:05 AM, Etsuro Fujita fujita.ets...@lab.ntt.co.jp
wrote:

 (2014/10/14 8:53), Robert Haas wrote:

 On Mon, Oct 13, 2014 at 3:30 PM, Bruce Momjian br...@momjian.us wrote:

 Uh, where are we on this patch?


 Probably it should be added to the upcoming CF.


 Done.

 https://commitfest.postgresql.org/action/patch_view?id=1599

 Thanks,

 Best regards,
 Etsuro Fujita


 --
 Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
 To make changes to your subscription:
 http://www.postgresql.org/mailpref/pgsql-hackers




-- 
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company


Re: [HACKERS] postgres_fdw behaves oddly

2014-10-13 Thread Bruce Momjian

Uh, where are we on this patch?

---

On Mon, Sep  8, 2014 at 09:30:32PM +0900, Etsuro Fujita wrote:
 (2014/09/02 18:55), Etsuro Fujita wrote:
  (2014/09/01 20:15), Etsuro Fujita wrote:
  While working on [1], I've found that postgres_fdw behaves oddly:
 
 I've revised the patch a bit further.  Please find attached a patch.
 
 Thanks,
 
 Best regards,
 Etsuro Fujita

 *** a/contrib/postgres_fdw/deparse.c
 --- b/contrib/postgres_fdw/deparse.c
 ***
 *** 252,257  foreign_expr_walker(Node *node,
 --- 252,265 
   if (var-varno == glob_cxt-foreignrel-relid 
   var-varlevelsup == 0)
   {
 + /*
 +  * System columns can't be sent to 
 remote.
 +  *
 +  * XXX: we should probably send ctid to 
 remote.
 +  */
 + if (var-varattno  0)
 + return false;
 + 
   /* Var belongs to foreign table */
   collation = var-varcollid;
   state = OidIsValid(collation) ? 
 FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
 ***
 *** 1261,1266  deparseVar(Var *node, deparse_expr_cxt *context)
 --- 1269,1279 
   if (node-varno == context-foreignrel-relid 
   node-varlevelsup == 0)
   {
 + /*
 +  * System columns shouldn't be examined here.
 +  */
 + Assert(node-varattno = 0);
 + 
   /* Var belongs to foreign table */
   deparseColumnRef(buf, node-varno, node-varattno, 
 context-root);
   }
 *** a/src/backend/optimizer/plan/createplan.c
 --- b/src/backend/optimizer/plan/createplan.c
 ***
 *** 20,25 
 --- 20,26 
   #include math.h
   
   #include access/skey.h
 + #include access/sysattr.h
   #include catalog/pg_class.h
   #include foreign/fdwapi.h
   #include miscadmin.h
 ***
 *** 1945,1950  create_foreignscan_plan(PlannerInfo *root, ForeignPath 
 *best_path,
 --- 1946,1953 
   RelOptInfo *rel = best_path-path.parent;
   Index   scan_relid = rel-relid;
   RangeTblEntry *rte;
 + Bitmapset  *attrs_used = NULL;
 + ListCell   *lc;
   int i;
   
   /* it should be a base rel... */
 ***
 *** 1993,2008  create_foreignscan_plan(PlannerInfo *root, ForeignPath 
 *best_path,
* bit of a kluge and might go away someday, so we intentionally leave 
 it
* out of the API presented to FDWs.
*/
   scan_plan-fsSystemCol = false;
   for (i = rel-min_attr; i  0; i++)
   {
 ! if (!bms_is_empty(rel-attr_needed[i - rel-min_attr]))
   {
   scan_plan-fsSystemCol = true;
   break;
   }
   }
   
   return scan_plan;
   }
   
 --- 1996,2030 
* bit of a kluge and might go away someday, so we intentionally leave 
 it
* out of the API presented to FDWs.
*/
 + 
 + /*
 +  * Add all the attributes needed for joins or final output.  Note: we 
 must
 +  * look at reltargetlist, not the attr_needed data, because attr_needed
 +  * isn't computed for inheritance child rels.
 +  */
 + pull_varattnos((Node *) rel-reltargetlist, rel-relid, attrs_used);
 + 
 + /* Add all the attributes used by restriction clauses. */
 + foreach(lc, rel-baserestrictinfo)
 + {
 + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
 + 
 + pull_varattnos((Node *) rinfo-clause, rel-relid, attrs_used);
 + }
 + 
 + /* Are any system columns requested from rel? */
   scan_plan-fsSystemCol = false;
   for (i = rel-min_attr; i  0; i++)
   {
 ! if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, 
 attrs_used))
   {
   scan_plan-fsSystemCol = true;
   break;
   }
   }
   
 + bms_free(attrs_used);
 + 
   return scan_plan;
   }
   

 
 -- 
 Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
 To make changes to your subscription:
 http://www.postgresql.org/mailpref/pgsql-hackers


-- 
  Bruce Momjian  br...@momjian.ushttp://momjian.us
  EnterpriseDB http://enterprisedb.com

  + Everyone has their own god. +


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-10-13 Thread Robert Haas
On Mon, Oct 13, 2014 at 3:30 PM, Bruce Momjian br...@momjian.us wrote:
 Uh, where are we on this patch?

Probably it should be added to the upcoming CF.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-09-08 Thread Etsuro Fujita
(2014/09/02 18:55), Etsuro Fujita wrote:
 (2014/09/01 20:15), Etsuro Fujita wrote:
 While working on [1], I've found that postgres_fdw behaves oddly:

I've revised the patch a bit further.  Please find attached a patch.

Thanks,

Best regards,
Etsuro Fujita
*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***
*** 252,257  foreign_expr_walker(Node *node,
--- 252,265 
  if (var-varno == glob_cxt-foreignrel-relid 
  	var-varlevelsup == 0)
  {
+ 	/*
+ 	 * System columns can't be sent to remote.
+ 	 *
+ 	 * XXX: we should probably send ctid to remote.
+ 	 */
+ 	if (var-varattno  0)
+ 		return false;
+ 
  	/* Var belongs to foreign table */
  	collation = var-varcollid;
  	state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
***
*** 1261,1266  deparseVar(Var *node, deparse_expr_cxt *context)
--- 1269,1279 
  	if (node-varno == context-foreignrel-relid 
  		node-varlevelsup == 0)
  	{
+ 		/*
+ 		 * System columns shouldn't be examined here.
+ 		 */
+ 		Assert(node-varattno = 0);
+ 
  		/* Var belongs to foreign table */
  		deparseColumnRef(buf, node-varno, node-varattno, context-root);
  	}
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
***
*** 20,25 
--- 20,26 
  #include math.h
  
  #include access/skey.h
+ #include access/sysattr.h
  #include catalog/pg_class.h
  #include foreign/fdwapi.h
  #include miscadmin.h
***
*** 1945,1950  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
--- 1946,1953 
  	RelOptInfo *rel = best_path-path.parent;
  	Index		scan_relid = rel-relid;
  	RangeTblEntry *rte;
+ 	Bitmapset  *attrs_used = NULL;
+ 	ListCell   *lc;
  	int			i;
  
  	/* it should be a base rel... */
***
*** 1993,2008  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (!bms_is_empty(rel-attr_needed[i - rel-min_attr]))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
  	return scan_plan;
  }
  
--- 1996,2030 
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
+ 
+ 	/*
+ 	 * Add all the attributes needed for joins or final output.  Note: we must
+ 	 * look at reltargetlist, not the attr_needed data, because attr_needed
+ 	 * isn't computed for inheritance child rels.
+ 	 */
+ 	pull_varattnos((Node *) rel-reltargetlist, rel-relid, attrs_used);
+ 
+ 	/* Add all the attributes used by restriction clauses. */
+ 	foreach(lc, rel-baserestrictinfo)
+ 	{
+ 		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ 
+ 		pull_varattnos((Node *) rinfo-clause, rel-relid, attrs_used);
+ 	}
+ 
+ 	/* Are any system columns requested from rel? */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, attrs_used))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
+ 	bms_free(attrs_used);
+ 
  	return scan_plan;
  }
  

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


Re: [HACKERS] postgres_fdw behaves oddly

2014-09-02 Thread Etsuro Fujita
(2014/09/01 20:15), Etsuro Fujita wrote:
 While working on [1], I've found that postgres_fdw behaves oddly:
 
 postgres=# create foreign table ft (a int) server loopback options
 (table_name 't');
 CREATE FOREIGN TABLE
 postgres=# select tableoid, * from ft;
   tableoid | a
 --+---
  16400 | 1
 (1 row)
 
 postgres=# select tableoid, * from ft where tableoid = 16400;
   tableoid | a
 --+---
 (0 rows)

 I think that one simple way of fixing such issues would be
 to consider unsafe to send to the remote a qual that contains any system
 columns.

I noticed the previous patch has overdone it.  Attached is an updated
version of the patch.

Thanks,

PS:
 [1] https://commitfest.postgresql.org/action/patch_view?id=1386

I'll update the patch in [1] on top of this version.

Best regards,
Etsuro Fujita
*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***
*** 252,257  foreign_expr_walker(Node *node,
--- 252,263 
  if (var-varno == glob_cxt-foreignrel-relid 
  	var-varlevelsup == 0)
  {
+ 	/*
+ 	 * System columns can't be sent to remote.
+ 	 */
+ 	if (var-varattno  0)
+ 		return false;
+ 
  	/* Var belongs to foreign table */
  	collation = var-varcollid;
  	state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
***
*** 20,25 
--- 20,26 
  #include math.h
  
  #include access/skey.h
+ #include access/sysattr.h
  #include catalog/pg_class.h
  #include foreign/fdwapi.h
  #include miscadmin.h
***
*** 1945,1950  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
--- 1946,1953 
  	RelOptInfo *rel = best_path-path.parent;
  	Index		scan_relid = rel-relid;
  	RangeTblEntry *rte;
+ 	Bitmapset  *attrs_used = NULL;
+ 	ListCell   *lc;
  	int			i;
  
  	/* it should be a base rel... */
***
*** 1993,2008  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (!bms_is_empty(rel-attr_needed[i - rel-min_attr]))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
  	return scan_plan;
  }
  
--- 1996,2030 
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
+ 
+ 	/*
+ 	 * Add all the attributes needed for joins or final output.  Note: we must
+ 	 * look at reltargetlist, not the attr_needed data, because attr_needed
+ 	 * isn't computed for inheritance child rels.
+ 	 */
+ 	pull_varattnos((Node *) rel-reltargetlist, rel-relid, attrs_used);
+ 
+ 	/* Add all the attributes used by restriction clauses. */
+ 	foreach(lc, rel-baserestrictinfo)
+ 	{
+ 		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ 
+ 		pull_varattnos((Node *) rinfo-clause, rel-relid, attrs_used);
+ 	}
+ 
+ 	/* Are any system columns requested from rel? */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, attrs_used))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
+ 	bms_free(attrs_used);
+ 
  	return scan_plan;
  }
  

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers


[HACKERS] postgres_fdw behaves oddly

2014-09-01 Thread Etsuro Fujita
While working on [1], I've found that postgres_fdw behaves oddly:

postgres=# create foreign table ft (a int) server loopback options
(table_name 't');
CREATE FOREIGN TABLE
postgres=# select tableoid, * from ft;
 tableoid | a
--+---
16400 | 1
(1 row)

postgres=# select tableoid, * from ft where tableoid = 16400;
 tableoid | a
--+---
(0 rows)

I think that this is because (a) the qual that contains tableoid can be
sent to the remote as shown in the EXPLAIN output:

postgres=# explain verbose select tableoid, * from ft where tableoid =
16400;
  QUERY PLAN
--
 Foreign Scan on public.ft  (cost=100.00..193.20 rows=2560 width=8)
   Output: tableoid, a
   Remote SQL: SELECT a FROM public.t WHERE ((tableoid = 16400::oid))
 Planning time: 0.110 ms
(4 rows)

and because (b) the tableoid value can be differs between the local and
the remote.  I think that one simple way of fixing such issues would be
to consider unsafe to send to the remote a qual that contains any system
columns (though we should probably give special treatment to quals
containing only ctid).  With the modification of postgres_fdw, we get
the right result:

postgres=# select tableoid, * from ft where tableoid = 16400;
 tableoid | a
--+---
16400 | 1
(1 row)

However, it's not complete enough.  Here is another surising result
(note no tableoid column in the select list):

postgres=# select * from ft where tableoid = 16400;
 a
---
(0 rows)

I think that this is because create_foreignscan_plan doesn't refer to
rel-baserestrictinfo when detecting whether any system columns are
requested.  By the additional modification of create_foreignscan_plan,
we get the right result:

postgres=# select * from ft where tableoid = 16400;
 a
---
 1
(1 row)

I'd also like to propose to change the function so as to make reference
to rel-reltargetlist, not to attr_needed, to match the code with other
places.  Please find attached a patch.

Thanks,

[1] https://commitfest.postgresql.org/action/patch_view?id=1386

Best regards,
Etsuro Fujita
*** a/contrib/postgres_fdw/deparse.c
--- b/contrib/postgres_fdw/deparse.c
***
*** 243,248  foreign_expr_walker(Node *node,
--- 243,254 
  Var		   *var = (Var *) node;
  
  /*
+  * System columns can't be sent to remote.
+  */
+ if (var-varattno  0)
+ 	return false;
+ 
+ /*
   * If the Var is from the foreign table, we consider its
   * collation (if any) safe to use.  If it is from another
   * table, we treat its collation the same way as we would a
*** a/src/backend/optimizer/plan/createplan.c
--- b/src/backend/optimizer/plan/createplan.c
***
*** 20,25 
--- 20,26 
  #include math.h
  
  #include access/skey.h
+ #include access/sysattr.h
  #include catalog/pg_class.h
  #include foreign/fdwapi.h
  #include miscadmin.h
***
*** 1945,1950  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
--- 1946,1953 
  	RelOptInfo *rel = best_path-path.parent;
  	Index		scan_relid = rel-relid;
  	RangeTblEntry *rte;
+ 	Bitmapset  *attrs_used = NULL;
+ 	ListCell   *lc;
  	int			i;
  
  	/* it should be a base rel... */
***
*** 1993,2008  create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (!bms_is_empty(rel-attr_needed[i - rel-min_attr]))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
  	return scan_plan;
  }
  
--- 1996,2030 
  	 * bit of a kluge and might go away someday, so we intentionally leave it
  	 * out of the API presented to FDWs.
  	 */
+ 
+ 	/*
+ 	 * Add all the attributes needed for joins or final output.  Note: we must
+ 	 * look at reltargetlist, not the attr_needed data, because attr_needed
+ 	 * isn't computed for inheritance child rels.
+ 	 */
+ 	pull_varattnos((Node *) rel-reltargetlist, rel-relid, attrs_used);
+ 
+ 	/* Add all the attributes used by restriction clauses. */
+ 	foreach(lc, rel-baserestrictinfo)
+ 	{
+ 		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
+ 
+ 		pull_varattnos((Node *) rinfo-clause, rel-relid, attrs_used);
+ 	}
+ 
+ 	/* Are any system columns requested from rel? */
  	scan_plan-fsSystemCol = false;
  	for (i = rel-min_attr; i  0; i++)
  	{
! 		if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, attrs_used))
  		{
  			scan_plan-fsSystemCol = true;
  			break;
  		}
  	}
  
+ 	bms_free(attrs_used);
+ 
  	return scan_plan;
  }
  

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers