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 1egvKg-0001rG-MC for pgsql-hackers@arkaria.postgresql.org; Wed, 31 Jan 2018 16:33:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1egvKf-0000NV-LM for pgsql-hackers@arkaria.postgresql.org; Wed, 31 Jan 2018 16:33: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_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1egvKf-0000NI-EH for pgsql-hackers@lists.postgresql.org; Wed, 31 Jan 2018 16:33:57 +0000 Received: from sraihb2.sra.co.jp ([202.32.10.6]) by magus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1egvKb-0002ju-PB for pgsql-hackers@postgresql.org; Wed, 31 Jan 2018 16:33:57 +0000 Received: from srascf.sra.co.jp (srascf [133.137.8.80]) by sraihb2.sra.co.jp (Postfix) with ESMTP id D11E22A15E7 for ; Thu, 1 Feb 2018 01:33:50 +0900 (JST) Received: from srascb.sra.co.jp (unknown [133.137.8.65]) by srascf.sra.co.jp with smtp id 2b34_04b3_75f3c6c8_2561_44f9_95bf_b842c7be4332; Thu, 01 Feb 2018 01:33:50 +0900 Received: from sranhm.sra.co.jp (osspc25 [133.137.174.97]) by srascb.sra.co.jp (Postfix) with ESMTP id B31392D6942 for ; Thu, 1 Feb 2018 01:33:50 +0900 (JST) Received: from yugo-n-ubuntu (sraihb-hub.sra.co.jp [133.137.8.6]) by sranhm.sra.co.jp (Postfix) with SMTP id 78FDFA12A7 for ; Thu, 1 Feb 2018 01:33:50 +0900 (JST) Date: Thu, 1 Feb 2018 01:33:49 +0900 From: Yugo Nagata To: pgsql-hackers@postgresql.org Subject: CURRENT OF causes an error when IndexOnlyScan is used Message-Id: <20180201013349.937dfc5f.nagata@sraoss.co.jp> X-Mailer: Sylpheed Pro 2.1.4 (GTK+ 2.24.23; x86_64-unknown-linux-gnu; Pro 2.1.4) Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Multipart=_Thu__1_Feb_2018_01_33_49_+0900_ySa7wxe+A=kZ5Lu=" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --Multipart=_Thu__1_Feb_2018_01_33_49_+0900_ySa7wxe+A=kZ5Lu= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Hi, I found that updating a cursor by using CURRENT OF causes the following error when the query is executed by IndexOnlyScan. ERROR: cannot extract system attribute from virtual tuple IndexOnlyScan returns a virtual tuple that doesn't have system column, so we can not get ctid in the same way of other plans. However, the error message is not convinient and users would not understand why the error occurs. Attached is a patch to fix this. By this fix, execCurrentOf get ctid from IndexScanDesc->xs_ctup.t_self when the plan is IndexOnlyScan, and it works sucessfully without errors. Here is the example of the error: ======= postgres=# create table test (i int primary key); CREATE TABLE postgres=# insert into test values(1); INSERT 0 1 postgres=# set enable_seqscan to off; SET postgres=# explain select * from test where i = 1; QUERY PLAN --------------------------------------------------------------------------- Index Only Scan using test_pkey on test (cost=0.15..8.17 rows=1 width=4) Index Cond: (i = 1) (2 rows) postgres=# begin; BEGIN postgres=# declare c cursor for select * from test where i = 1; DECLARE CURSOR postgres=# fetch from c; i --- 1 (1 row) postgres=# update test set i=i+1 where current of c; ERROR: cannot extract system attribute from virtual tuple ======= The patch fixes the error and allows this update successfully. Regards, -- Yugo Nagata --Multipart=_Thu__1_Feb_2018_01_33_49_+0900_ySa7wxe+A=kZ5Lu= Content-Type: text/x-diff; name="current_of_index_only_scan.patch" Content-Disposition: attachment; filename="current_of_index_only_scan.patch" Content-Transfer-Encoding: 7bit diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c index ce7d4ac..b37cf3d 100644 --- a/src/backend/executor/execCurrent.c +++ b/src/backend/executor/execCurrent.c @@ -19,6 +19,7 @@ #include "utils/lsyscache.h" #include "utils/portal.h" #include "utils/rel.h" +#include "access/relscan.h" static char *fetch_cursor_param_value(ExprContext *econtext, int paramId); @@ -183,21 +184,35 @@ execCurrentOf(CurrentOfExpr *cexpr, if (TupIsNull(scanstate->ss_ScanTupleSlot)) return false; - /* Use slot_getattr to catch any possible mistakes */ - tuple_tableoid = - DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot, - TableOidAttributeNumber, - &lisnull)); - Assert(!lisnull); - tuple_tid = (ItemPointer) - DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot, - SelfItemPointerAttributeNumber, - &lisnull)); - Assert(!lisnull); - - Assert(tuple_tableoid == table_oid); - - *current_tid = *tuple_tid; + /* In IndexOnlyScan case, the tuple stored in ss_ScanTupleSlot is a + * virtual tuple that does not have ctid column, so we have to get TID + * from xs_ctup.t_self. */ + if (IsA(scanstate, IndexOnlyScanState)) + { + IndexScanDesc scan = ((IndexOnlyScanState *)scanstate)->ScanDesc; + + Assert(RelationGetRelid(scan.heapRelation) == table_oid); + + *current_tid = scan->xs_ctup.t_self; + } + else + { + /* Use slot_getattr to catch any possible mistakes */ + tuple_tableoid = + DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot, + TableOidAttributeNumber, + &lisnull)); + Assert(!lisnull); + tuple_tid = (ItemPointer) + DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot, + SelfItemPointerAttributeNumber, + &lisnull)); + Assert(!lisnull); + + Assert(tuple_tableoid == table_oid); + + *current_tid = *tuple_tid; + } return true; } --Multipart=_Thu__1_Feb_2018_01_33_49_+0900_ySa7wxe+A=kZ5Lu=--