Re: Pluggable Storage - Andres's take

From: Andres Freund <andres(at)anarazel(dot)de>
To: Haribabu Kommi <kommi(dot)haribabu(at)gmail(dot)com>
Cc: Dmitry Dolgov <9erthalion6(at)gmail(dot)com>, Alvaro Herrera <alvherre(at)2ndquadrant(dot)com>, Alexander Korotkov <a(dot)korotkov(at)postgrespro(dot)ru>, Pg Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: Pluggable Storage - Andres's take
Date: 2018-12-11 01:47:47
Message-ID: 20181211014747.rdspcq26l2gmixvn@alap3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

Thanks for these changes. I've merged a good chunk of them.

On 2018-11-16 12:05:26 +1100, Haribabu Kommi wrote:
> diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
> index c3960dc91f..3254e30a45 100644
> --- a/src/backend/access/heap/heapam_handler.c
> +++ b/src/backend/access/heap/heapam_handler.c
> @@ -1741,7 +1741,7 @@ heapam_scan_analyze_next_tuple(TableScanDesc sscan, TransactionId OldestXmin, do
> {
> HeapScanDesc scan = (HeapScanDesc) sscan;
> Page targpage;
> - OffsetNumber targoffset = scan->rs_cindex;
> + OffsetNumber targoffset;
> OffsetNumber maxoffset;
> BufferHeapTupleTableSlot *hslot;
>
> @@ -1751,7 +1751,9 @@ heapam_scan_analyze_next_tuple(TableScanDesc sscan, TransactionId OldestXmin, do
> maxoffset = PageGetMaxOffsetNumber(targpage);
>
> /* Inner loop over all tuples on the selected page */
> - for (targoffset = scan->rs_cindex; targoffset <= maxoffset; targoffset++)
> + for (targoffset = scan->rs_cindex ? scan->rs_cindex : FirstOffsetNumber;
> + targoffset <= maxoffset;
> + targoffset++)
> {
> ItemId itemid;
> HeapTuple targtuple = &hslot->base.tupdata;

I thought it was better to fix the initialization for rs_cindex - any
reason you didn't go for that?

> diff --git a/src/backend/access/heap/heapam_visibility.c b/src/backend/access/heap/heapam_visibility.c
> index 8233475aa0..7bad246f55 100644
> --- a/src/backend/access/heap/heapam_visibility.c
> +++ b/src/backend/access/heap/heapam_visibility.c
> @@ -1838,8 +1838,10 @@ HeapTupleSatisfies(HeapTuple stup, Snapshot snapshot, Buffer buffer)
> case NON_VACUUMABLE_VISIBILTY:
> return HeapTupleSatisfiesNonVacuumable(stup, snapshot, buffer);
> break;
> - default:
> + case END_OF_VISIBILITY:
> Assert(0);
> break;
> }
> +
> + return false; /* keep compiler quiet */

I don't understand why END_OF_VISIBILITY is good idea? I now removed
END_OF_VISIBILITY, and the default case.

> @@ -593,6 +594,10 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
> if (myState->rel->rd_rel->relhasoids)
> slot->tts_tupleOid = InvalidOid;
>
> + /* Materialize the slot */
> + if (!TTS_IS_VIRTUAL(slot))
> + ExecMaterializeSlot(slot);
> +
> table_insert(myState->rel,
> slot,
> myState->output_cid,

What's the point of adding materialization here?

> @@ -570,6 +563,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
> Assert(TTS_IS_HEAPTUPLE(scanslot) ||
> TTS_IS_BUFFERTUPLE(scanslot));
>
> + if (hslot->tuple == NULL)
> + ExecMaterializeSlot(scanslot);
> +
> d = heap_getsysattr(hslot->tuple, attnum,
> scanslot->tts_tupleDescriptor,
> op->resnull);

Same?

> diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
> index e055c0a7c6..34ef86a5bd 100644
> --- a/src/backend/executor/execMain.c
> +++ b/src/backend/executor/execMain.c
> @@ -2594,7 +2594,7 @@ EvalPlanQual(EState *estate, EPQState *epqstate,
> * datums that may be present in copyTuple). As with the next step, this
> * is to guard against early re-use of the EPQ query.
> */
> - if (!TupIsNull(slot))
> + if (!TupIsNull(slot) && !TTS_IS_VIRTUAL(slot))
> ExecMaterializeSlot(slot);

Same?

> #if FIXME
> @@ -2787,16 +2787,7 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
> if (isNull)
> continue;
>
> - elog(ERROR, "frak, need to implement ROW_MARK_COPY");
> -#ifdef FIXME
> - // FIXME: this should just deform the tuple and store it as a
> - // virtual one.
> - tuple = table_tuple_by_datum(erm->relation, datum, erm->relid);
> -
> - /* store tuple */
> - EvalPlanQualSetTuple(epqstate, erm->rti, tuple);
> -#endif
> -
> + ExecForceStoreHeapTupleDatum(datum, slot);
> }
> }
> }

Cool.

> diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
> index 56880e3d16..36ca07beb2 100644
> --- a/src/backend/executor/nodeBitmapHeapscan.c
> +++ b/src/backend/executor/nodeBitmapHeapscan.c
> @@ -224,6 +224,18 @@ BitmapHeapNext(BitmapHeapScanState *node)
>
> BitmapAdjustPrefetchIterator(node, tbmres);
>
> + /*
> + * Ignore any claimed entries past what we think is the end of the
> + * relation. (This is probably not necessary given that we got at
> + * least AccessShareLock on the table before performing any of the
> + * indexscans, but let's be safe.)
> + */
> + if (tbmres->blockno >= scan->rs_nblocks)
> + {
> + node->tbmres = tbmres = NULL;
> + continue;
> + }
> +

I moved this into the storage engine, there just was a minor bug
preventing the already existing check from taking effect. I don't think
we should expose this kind of thing to the outside of the storage
engine.

> diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
> index 54382aba88..ea48e1d6e8 100644
> --- a/src/backend/parser/gram.y
> +++ b/src/backend/parser/gram.y
> @@ -4037,7 +4037,6 @@ CreateStatsStmt:
> *
> *****************************************************************************/
>
> -// PBORKED: storage option
> CreateAsStmt:
> CREATE OptTemp TABLE create_as_target AS SelectStmt opt_with_data
> {
> @@ -4068,14 +4067,16 @@ CreateAsStmt:
> ;
>
> create_as_target:
> - qualified_name opt_column_list OptWith OnCommitOption OptTableSpace
> + qualified_name opt_column_list table_access_method_clause
> + OptWith OnCommitOption OptTableSpace
> {
> $$ = makeNode(IntoClause);
> $$->rel = $1;
> $$->colNames = $2;
> - $$->options = $3;
> - $$->onCommit = $4;
> - $$->tableSpaceName = $5;
> + $$->accessMethod = $3;
> + $$->options = $4;
> + $$->onCommit = $5;
> + $$->tableSpaceName = $6;
> $$->viewQuery = NULL;
> $$->skipData = false; /* might get changed later */
> }
> @@ -4125,14 +4126,15 @@ CreateMatViewStmt:
> ;
>
> create_mv_target:
> - qualified_name opt_column_list opt_reloptions OptTableSpace
> + qualified_name opt_column_list table_access_method_clause opt_reloptions OptTableSpace
> {
> $$ = makeNode(IntoClause);
> $$->rel = $1;
> $$->colNames = $2;
> - $$->options = $3;
> + $$->accessMethod = $3;
> + $$->options = $4;
> $$->onCommit = ONCOMMIT_NOOP;
> - $$->tableSpaceName = $4;
> + $$->tableSpaceName = $5;
> $$->viewQuery = NULL; /* filled at analysis time */
> $$->skipData = false; /* might get changed later */
> }

Cool. I wonder if we should also somehow support SELECT INTO w/ USING?
You've apparently started to do so with?

> diff --git a/src/test/regress/expected/create_am.out b/src/test/regress/expected/create_am.out
> index 47dd885c4e..a4094ca3f1 100644
> --- a/src/test/regress/expected/create_am.out
> +++ b/src/test/regress/expected/create_am.out
> @@ -99,3 +99,81 @@ HINT: Use DROP ... CASCADE to drop the dependent objects too.
> -- Drop access method cascade
> DROP ACCESS METHOD gist2 CASCADE;
> NOTICE: drop cascades to index grect2ind2
> +-- Create a heap2 table am handler with heapam handler
> +CREATE ACCESS METHOD heap2 TYPE TABLE HANDLER heap_tableam_handler;
> +SELECT * FROM pg_am where amtype = 't';
> + amname | amhandler | amtype
> +--------+----------------------+--------
> + heap | heap_tableam_handler | t
> + heap2 | heap_tableam_handler | t
> +(2 rows)
> +
> +CREATE TABLE tbl_heap2(f1 int, f2 char(100)) using heap2;
> +INSERT INTO tbl_heap2 VALUES(generate_series(1,10), 'Test series');
> +SELECT count(*) FROM tbl_heap2;
> + count
> +-------
> + 10
> +(1 row)
> +
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'tbl_heap2';
> + relname | relkind | amname
> +-----------+---------+--------
> + tbl_heap2 | r | heap2
> +(1 row)
> +
> +-- create table as using heap2
> +CREATE TABLE tblas_heap2 using heap2 AS select * from tbl_heap2;
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'tblas_heap2';
> + relname | relkind | amname
> +-------------+---------+--------
> + tblas_heap2 | r | heap2
> +(1 row)
> +
> +--
> +-- select into doesn't support new syntax, so it should be
> +-- default access method.
> +--
> +SELECT INTO tblselectinto_heap from tbl_heap2;
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'tblselectinto_heap';
> + relname | relkind | amname
> +--------------------+---------+--------
> + tblselectinto_heap | r | heap
> +(1 row)
> +
> +DROP TABLE tblselectinto_heap;
> +-- create materialized view using heap2
> +CREATE MATERIALIZED VIEW mv_heap2 USING heap2 AS
> + SELECT * FROM tbl_heap2;
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'mv_heap2';
> + relname | relkind | amname
> +----------+---------+--------
> + mv_heap2 | m | heap2
> +(1 row)
> +
> +-- Try creating the unsupported relation kinds with using syntax
> +CREATE VIEW test_view USING heap2 AS SELECT * FROM tbl_heap2;
> +ERROR: syntax error at or near "USING"
> +LINE 1: CREATE VIEW test_view USING heap2 AS SELECT * FROM tbl_heap2...
> + ^
> +CREATE SEQUENCE test_seq USING heap2;
> +ERROR: syntax error at or near "USING"
> +LINE 1: CREATE SEQUENCE test_seq USING heap2;
> + ^
> +-- Drop table access method, but fails as objects depends on it
> +DROP ACCESS METHOD heap2;
> +ERROR: cannot drop access method heap2 because other objects depend on it
> +DETAIL: table tbl_heap2 depends on access method heap2
> +table tblas_heap2 depends on access method heap2
> +materialized view mv_heap2 depends on access method heap2
> +HINT: Use DROP ... CASCADE to drop the dependent objects too.
> +-- Drop table access method with cascade
> +DROP ACCESS METHOD heap2 CASCADE;
> +NOTICE: drop cascades to 3 other objects
> +DETAIL: drop cascades to table tbl_heap2
> +drop cascades to table tblas_heap2
> +drop cascades to materialized view mv_heap2
> diff --git a/src/test/regress/sql/create_am.sql b/src/test/regress/sql/create_am.sql
> index 3e0ac104f3..0472a60f20 100644
> --- a/src/test/regress/sql/create_am.sql
> +++ b/src/test/regress/sql/create_am.sql
> @@ -66,3 +66,49 @@ DROP ACCESS METHOD gist2;
>
> -- Drop access method cascade
> DROP ACCESS METHOD gist2 CASCADE;
> +
> +-- Create a heap2 table am handler with heapam handler
> +CREATE ACCESS METHOD heap2 TYPE TABLE HANDLER heap_tableam_handler;
> +
> +SELECT * FROM pg_am where amtype = 't';
> +
> +CREATE TABLE tbl_heap2(f1 int, f2 char(100)) using heap2;
> +INSERT INTO tbl_heap2 VALUES(generate_series(1,10), 'Test series');
> +SELECT count(*) FROM tbl_heap2;
> +
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'tbl_heap2';
> +
> +-- create table as using heap2
> +CREATE TABLE tblas_heap2 using heap2 AS select * from tbl_heap2;
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'tblas_heap2';
> +
> +--
> +-- select into doesn't support new syntax, so it should be
> +-- default access method.
> +--
> +SELECT INTO tblselectinto_heap from tbl_heap2;
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'tblselectinto_heap';
> +
> +DROP TABLE tblselectinto_heap;
> +
> +-- create materialized view using heap2
> +CREATE MATERIALIZED VIEW mv_heap2 USING heap2 AS
> + SELECT * FROM tbl_heap2;
> +
> +SELECT r.relname, r.relkind, a.amname from pg_class as r, pg_am as a
> + where a.oid = r.relam AND r.relname = 'mv_heap2';
> +
> +-- Try creating the unsupported relation kinds with using syntax
> +CREATE VIEW test_view USING heap2 AS SELECT * FROM tbl_heap2;
> +
> +CREATE SEQUENCE test_seq USING heap2;
> +
> +
> +-- Drop table access method, but fails as objects depends on it
> +DROP ACCESS METHOD heap2;
> +
> +-- Drop table access method with cascade
> +DROP ACCESS METHOD heap2 CASCADE;
> --
> 2.18.0.windows.1

Nice!

Greetings,

Andres Freund

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Amit Langote 2018-12-11 02:08:41 Re: pg_dump emits ALTER TABLE ONLY partitioned_table
Previous Message Michael Paquier 2018-12-11 01:43:17 Re: Add timeline to partial WAL segments