From 2c1414f2e847577174ba3087868e4920342dfeb1 Mon Sep 17 00:00:00 2001
From: kommih <haribabuk@fast.au.fujitsu.com>
Date: Thu, 1 Nov 2018 12:00:10 +1100
Subject: [PATCH 3/3] First draft of pluggable-storage documentation

---
 doc/src/sgml/{indexam.sgml => am.sgml}     | 590 ++++++++++++++++++++-
 doc/src/sgml/catalogs.sgml                 |   5 +-
 doc/src/sgml/config.sgml                   |  24 +
 doc/src/sgml/filelist.sgml                 |   2 +-
 doc/src/sgml/postgres.sgml                 |   2 +-
 doc/src/sgml/ref/create_access_method.sgml |  12 +-
 doc/src/sgml/ref/create_table.sgml         |  18 +-
 doc/src/sgml/ref/create_table_as.sgml      |  14 +
 doc/src/sgml/release-9.6.sgml              |   2 +-
 doc/src/sgml/xindex.sgml                   |   2 +-
 10 files changed, 640 insertions(+), 31 deletions(-)
 rename doc/src/sgml/{indexam.sgml => am.sgml} (78%)

diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/am.sgml
similarity index 78%
rename from doc/src/sgml/indexam.sgml
rename to doc/src/sgml/am.sgml
index beb99d1831..dc13bc1073 100644
--- a/doc/src/sgml/indexam.sgml
+++ b/doc/src/sgml/am.sgml
@@ -1,16 +1,20 @@
-<!-- doc/src/sgml/indexam.sgml -->
+<!-- doc/src/sgml/am.sgml -->
 
-<chapter id="indexam">
- <title>Index Access Method Interface Definition</title>
+<chapter id="am">
+ <title>Access Method Interface Definition</title>
 
   <para>
    This chapter defines the interface between the core
-   <productname>PostgreSQL</productname> system and <firstterm>index access
-   methods</firstterm>, which manage individual index types.  The core system
-   knows nothing about indexes beyond what is specified here, so it is
-   possible to develop entirely new index types by writing add-on code.
+   <productname>PostgreSQL</productname> system and <firstterm>access
+   methods</firstterm>, which manage individual <literal>INDEX</literal> 
+   and <literal>TABLE</literal> types.  The core system knows nothing
+   about these access methods beyond what is specified here, so it is
+   possible to develop entirely new access method types by writing add-on code.
   </para>
-
+ 
+ <sect1 id="index-access-methods">
+  <title>Overview of Index access methods</title>
+  
   <para>
    All indexes in <productname>PostgreSQL</productname> are what are known
    technically as <firstterm>secondary indexes</firstterm>; that is, the index is
@@ -42,8 +46,8 @@
    dead tuples are reclaimed (by vacuuming) when the dead tuples themselves
    are reclaimed.
   </para>
-
- <sect1 id="index-api">
+  
+ <sect2 id="index-api">
   <title>Basic API Structure for Indexes</title>
 
   <para>
@@ -217,9 +221,9 @@ typedef struct IndexAmRoutine
    conditions.
   </para>
 
- </sect1>
+ </sect2>
 
- <sect1 id="index-functions">
+ <sect2 id="index-functions">
   <title>Index Access Method Functions</title>
 
   <para>
@@ -709,9 +713,11 @@ amparallelrescan (IndexScanDesc scan);
    the beginning.
   </para>
 
- </sect1>
+ </sect2>
+ 
+ 
 
- <sect1 id="index-scanning">
+ <sect2 id="index-scanning">
   <title>Index Scanning</title>
 
   <para>
@@ -864,9 +870,9 @@ amparallelrescan (IndexScanDesc scan);
    if its internal implementation is unsuited to one API or the other.
   </para>
 
- </sect1>
+ </sect2>
 
- <sect1 id="index-locking">
+ <sect2 id="index-locking">
   <title>Index Locking Considerations</title>
 
   <para>
@@ -978,9 +984,9 @@ amparallelrescan (IndexScanDesc scan);
    reduce the frequency of such transaction cancellations.
   </para>
 
- </sect1>
+ </sect2>
 
- <sect1 id="index-unique-checks">
+ <sect2 id="index-unique-checks">
   <title>Index Uniqueness Checks</title>
 
   <para>
@@ -1127,9 +1133,9 @@ amparallelrescan (IndexScanDesc scan);
     </itemizedlist>
   </para>
 
- </sect1>
+ </sect2>
 
- <sect1 id="index-cost-estimation">
+ <sect2 id="index-cost-estimation">
   <title>Index Cost Estimation Functions</title>
 
   <para>
@@ -1376,5 +1382,549 @@ cost_qual_eval(&amp;index_qual_cost, path-&gt;indexquals, root);
    Examples of cost estimator functions can be found in
    <filename>src/backend/utils/adt/selfuncs.c</filename>.
   </para>
+ </sect2>
  </sect1>
+ 
+ <sect1 id="table-access-methods">
+  <title>Overview of Table access methods </title>
+  
+  <para>
+   All Tables in <productname>PostgreSQL</productname> are the primary data store.
+   Each table is stored as its own physical <firstterm>relation</firstterm> and so
+   is described by an entry in the <structname>pg_class</structname> catalog.
+   The contents of an table are entirely under the control of its access method.
+   (All the access methods furthermore use the standard page layout described in
+   <xref linkend="storage-page-layout"/>.)
+  </para>
+  
+ <sect2 id="table-api">
+  <title>Table access method API</title>
+  
+  <para>
+   Each table access method is described by a row in the
+   <link linkend="catalog-pg-am"><structname>pg_am</structname></link>
+   system catalog.  The <structname>pg_am</structname> entry
+   specifies a name and a <firstterm>handler function</firstterm> for the access
+   method.  These entries can be created and deleted using the
+   <xref linkend="sql-create-access-method"/> and
+   <xref linkend="sql-drop-access-method"/> SQL commands.
+  </para>
+
+  <para>
+   A table access method handler function must be declared to accept a
+   single argument of type <type>internal</type> and to return the
+   pseudo-type <type>table_am_handler</type>.  The argument is a dummy value that
+   simply serves to prevent handler functions from being called directly from
+   SQL commands.  The result of the function must be a palloc'd struct of
+   type <structname>TableAmRoutine</structname>, which contains everything
+   that the core code needs to know to make use of the table access method.
+   The <structname>TableAmRoutine</structname> struct, also called the access
+   method's <firstterm>API struct</firstterm>, includes fields specifying assorted
+   fixed properties of the access method, such as whether it can support
+   bitmap scans.  More importantly, it contains pointers to support
+   functions for the access method, which do all of the real work to access
+   tables.  These support functions are plain C functions and are not
+   visible or callable at the SQL level.  The support functions are described
+   in <xref linkend="table-functions"/>.
+  </para>
+
+  <para>
+   The structure <structname>TableAmRoutine</structname> is defined thus:
+<programlisting>
+typedef struct TableAmRoutine
+{
+    NodeTag     type;
+
+    SlotCallbacks_function slot_callbacks;
+
+    SnapshotSatisfies_function snapshot_satisfies;
+    SnapshotSatisfiesUpdate_function snapshot_satisfiesUpdate;
+    SnapshotSatisfiesVacuum_function snapshot_satisfiesVacuum;
+
+    /* Operations on physical tuples */
+    TupleInsert_function tuple_insert;
+    TupleInsertSpeculative_function tuple_insert_speculative;
+    TupleCompleteSpeculative_function tuple_complete_speculative;
+    TupleUpdate_function tuple_update;
+    TupleDelete_function tuple_delete;
+    TupleFetchRowVersion_function tuple_fetch_row_version;
+    TupleLock_function tuple_lock;
+    MultiInsert_function multi_insert;
+    TupleGetLatestTid_function tuple_get_latest_tid;
+    TupleFetchFollow_function tuple_fetch_follow;
+
+    GetTupleData_function get_tuple_data;
+
+    RelationVacuum_function relation_vacuum;
+    RelationScanAnalyzeNextBlock_function scan_analyze_next_block;
+    RelationScanAnalyzeNextTuple_function scan_analyze_next_tuple;
+    RelationCopyForCluster_function relation_copy_for_cluster;
+    RelationSync_function relation_sync;
+
+    /* Operations on relation scans */
+    ScanBegin_function scan_begin;
+    ScanSetlimits_function scansetlimits;
+    ScanGetnextSlot_function scan_getnextslot;
+
+    BitmapPagescan_function scan_bitmap_pagescan;
+    BitmapPagescanNext_function scan_bitmap_pagescan_next;
+
+    SampleScanNextBlock_function scan_sample_next_block;
+    SampleScanNextTuple_function scan_sample_next_tuple;
+
+    ScanEnd_function scan_end;
+    ScanRescan_function scan_rescan;
+    ScanUpdateSnapshot_function scan_update_snapshot;
+
+    BeginIndexFetchTable_function begin_index_fetch;
+    EndIndexFetchTable_function reset_index_fetch;
+    EndIndexFetchTable_function end_index_fetch;
+
+
+    IndexBuildRangeScan_function index_build_range_scan;
+    IndexValidateScan_function index_validate_scan;
+
+    CreateInitFork_function CreateInitFork;
+}           TableAmRoutine;
+</programlisting>
+  </para>
+  
+  <para>
+   An individual table is defined by a
+   <link linkend="catalog-pg-class"><structname>pg_class</structname></link>
+   entry that describes it as a physical relation.
+  </para>
+   
+ </sect2>
+ 
+ <sect2 id="table-functions">
+  <title>Table Access Method Functions</title>
+
+  <para>
+   The table construction and maintenance functions that an table access
+   method must provide in <structname>TableAmRoutine</structname> are:
+  </para>
+
+  <para>
+<programlisting>
+TupleTableSlotOps *
+slot_callbacks (Relation relation);
+</programlisting>
+   API to access the slot specific methods;
+   Following methods are available; 
+   <structname>TTSOpsVirtual</structname>,
+   <structname>TTSOpsHeapTuple</structname>,
+   <structname>TTSOpsMinimalTuple</structname>,
+   <structname>TTSOpsBufferTuple</structname>,
+  </para>
+  
+  <para>
+<programlisting>
+bool
+snapshot_satisfies (TupleTableSlot *slot, Snapshot snapshot);
+</programlisting>
+   API to check whether the provided slot is visible to the current
+   transaction according the snapshot.
+  </para>
+ 
+  <para>
+<programlisting>
+Oid
+tuple_insert (Relation rel, TupleTableSlot *slot, CommandId cid,
+              int options, BulkInsertState bistate);
+</programlisting>
+   API to insert the tuple and provide the <literal>ItemPointerData</literal>
+   where the tuple is successfully inserted.
+  </para>
+  
+  <para>
+<programlisting>
+Oid
+tuple_insert_speculative (Relation rel,
+                         TupleTableSlot *slot,
+                         CommandId cid,
+                         int options,
+                         BulkInsertState bistate,
+                         uint32 specToken);
+</programlisting>
+   API to insert the tuple with a speculative token. This API is similar
+   like <literal>tuple_insert</literal>, with additional speculative
+   information.
+  </para>
+  
+  <para>
+<programlisting>
+void
+tuple_complete_speculative (Relation rel,
+                          TupleTableSlot *slot,
+                          uint32 specToken,
+                          bool succeeded);
+</programlisting>
+   API to complete the state of the tuple inserted by the API <literal>tuple_insert_speculative</literal>
+   with the successful completion of the index insert.
+  </para>
+  
+  
+  <para>
+<programlisting>
+HTSU_Result
+tuple_update (Relation relation,
+             ItemPointer otid,
+             TupleTableSlot *slot,
+             CommandId cid,
+             Snapshot crosscheck,
+             bool wait,
+             HeapUpdateFailureData *hufd,
+             LockTupleMode *lockmode,
+             bool *update_indexes);
+</programlisting>
+   API to update the existing tuple with new data.
+  </para>
+  
+  
+  <para>
+<programlisting>
+HTSU_Result
+tuple_delete (Relation relation,
+             ItemPointer tid,
+             CommandId cid,
+             Snapshot crosscheck,
+             bool wait,
+             HeapUpdateFailureData *hufd,
+             bool changingPart);
+</programlisting>
+   API to delete the existing tuple.
+  </para>
+  
+  
+  <para>
+<programlisting>
+bool
+tuple_fetch_row_version (Relation relation,
+                       ItemPointer tid,
+                       Snapshot snapshot,
+                       TupleTableSlot *slot,
+                       Relation stats_relation);
+</programlisting>
+   API to fetch and store the Buffered Heap tuple in the provided slot
+   based on the ItemPointer.
+  </para>
+  
+  
+  <para>
+<programlisting>
+HTSU_Result
+TupleLock_function (Relation relation,
+                   ItemPointer tid,
+                   Snapshot snapshot,
+                   TupleTableSlot *slot,
+                   CommandId cid,
+                   LockTupleMode mode,
+                   LockWaitPolicy wait_policy,
+                   uint8 flags,
+                   HeapUpdateFailureData *hufd);
+</programlisting>
+   API to lock the specified the ItemPointer tuple and fetches the newest version of
+   its tuple and TID.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+multi_insert (Relation relation, TupleTableSlot **slots, int nslots,
+              CommandId cid, int options, BulkInsertState bistate);
+</programlisting>
+   API to insert multiple tuples at a time into the relation.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+tuple_get_latest_tid (Relation relation,
+                    Snapshot snapshot,
+                    ItemPointer tid);
+</programlisting>
+   API to get the the latest TID of the tuple with the given itempointer.
+  </para>
+  
+  
+  <para>
+<programlisting>
+bool
+tuple_fetch_follow (struct IndexFetchTableData *scan,
+                  ItemPointer tid,
+                  Snapshot snapshot,
+                  TupleTableSlot *slot,
+                  bool *call_again, bool *all_dead);
+</programlisting>
+   API to get the all the tuples of the page that satisfies itempointer.
+  </para>
+  
+  
+  <para>
+<programlisting>
+tuple_data
+get_tuple_data (TupleTableSlot *slot, tuple_data_flags flags);
+</programlisting>
+   API to return the internal structure members of the HeapTuple.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+relation_vacuum (Relation onerel, int options,
+                struct VacuumParams *params, BufferAccessStrategy bstrategy);
+</programlisting>
+   API to perform vacuum for one heap relation.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+scan_analyze_next_block (TableScanDesc scan, BlockNumber blockno,
+                      BufferAccessStrategy bstrategy);
+</programlisting>
+   API to fill the scan descriptor with the buffer of the specified block.
+  </para>
+  
+  
+  <para>
+<programlisting>
+bool
+scan_analyze_next_tuple (TableScanDesc scan, TransactionId OldestXmin,
+                      double *liverows, double *deadrows, TupleTableSlot *slot));
+</programlisting>
+   API to analyze the block and fill the buffered heap tuple in the slot and also
+   provide the live and dead rows.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+relation_copy_for_cluster (Relation NewHeap, Relation OldHeap, Relation OldIndex,
+                       bool use_sort,
+                       TransactionId OldestXmin, TransactionId FreezeXid, MultiXactId MultiXactCutoff,
+                       double *num_tuples, double *tups_vacuumed, double *tups_recently_dead);
+</programlisting>
+   API to copy one relation to another relation eith using the Index or table scan.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+relation_sync (Relation relation);
+</programlisting>
+   API to sync the relation to disk, useful for the cases where no WAL is written.
+  </para>
+  
+  
+  <para>
+<programlisting>
+TableScanDesc
+scan_begin (Relation relation,
+            Snapshot snapshot,
+            int nkeys, ScanKey key,
+            ParallelTableScanDesc parallel_scan,
+            bool allow_strat,
+            bool allow_sync,
+            bool allow_pagemode,
+            bool is_bitmapscan,
+            bool is_samplescan,
+            bool temp_snap);
+</programlisting>
+   API to start the relation scan for the provided relation and returns the
+   <structname>TableScanDesc</structname> structure.
+  </para>
+  
+  
+    <para>
+<programlisting>
+void
+scansetlimits (TableScanDesc sscan, BlockNumber startBlk, BlockNumber numBlks);
+</programlisting>
+   API to fix the relation scan range limits.
+  </para>
+  
+  
+    <para>
+<programlisting>
+TupleTableSlot *
+scan_getnextslot (TableScanDesc scan,
+                 ScanDirection direction, TupleTableSlot *slot);
+</programlisting>
+   API to fill the next visible tuple from the relation scan in the provided slot
+   and return it.
+  </para>
+  
+  
+    <para>
+<programlisting>
+bool
+scan_bitmap_pagescan (TableScanDesc scan,
+                    TBMIterateResult *tbmres);
+</programlisting>
+   API to scan the relation and fill the scan description bitmap with valid item pointers
+   for the specified block.
+  </para>
+  
+  
+    <para>
+<programlisting>
+bool
+scan_bitmap_pagescan_next (TableScanDesc scan,
+                        TupleTableSlot *slot);
+</programlisting>
+   API to fill the buffered heap tuple data from the bitmap scanned item pointers and store
+   it in the provided slot.
+  </para>
+  
+  
+    <para>
+<programlisting>
+bool
+scan_sample_next_block (TableScanDesc scan, struct SampleScanState *scanstate);
+</programlisting>
+   API to scan the relation and fill the scan description bitmap with valid item pointers
+   for the specified block provided by the sample method.
+  </para>
+  
+  
+    <para>
+<programlisting>
+bool
+scan_sample_next_tuple (TableScanDesc scan, struct SampleScanState *scanstate, TupleTableSlot *slot);
+</programlisting>
+   API to fill the buffered heap tuple data from the bitmap scanned item pointers based on the sample
+   method and store it in the provided slot.
+  </para>
+  
+  
+    <para>
+<programlisting>
+void
+scan_end (TableScanDesc scan);
+</programlisting>
+   API to end the relation scan.
+  </para>
+  
+  
+    <para>
+<programlisting>
+void
+scan_rescan (TableScanDesc scan, ScanKey key, bool set_params,
+             bool allow_strat, bool allow_sync, bool allow_pagemode);
+</programlisting>
+   API to restart the relation scan with provided data.
+  </para>
+  
+  
+  <para>
+<programlisting>
+void
+scan_update_snapshot (TableScanDesc scan, Snapshot snapshot);
+</programlisting>
+   API to update the relation scan with the new snapshot.
+  </para>
+  
+  <para>
+<programlisting>
+IndexFetchTableData *
+begin_index_fetch (Relation relation);
+</programlisting>
+   API to prepare the <structname>IndexFetchTableData</structname> for the relation.
+  </para>
+  
+  <para>
+<programlisting>
+void
+reset_index_fetch (struct IndexFetchTableData* data);
+</programlisting>
+   API to reset the prepared internal members of the <structname>IndexFetchTableData</structname>.
+  </para>
+  
+  <para>
+<programlisting>
+void
+end_index_fetch (struct IndexFetchTableData* data);
+</programlisting>
+   API to clear and free the <structname>IndexFetchTableData</structname>.
+  </para>
+  
+    <para>
+<programlisting>
+double
+index_build_range_scan (Relation heapRelation,
+                       Relation indexRelation,
+                       IndexInfo *indexInfo,
+                       bool allow_sync,
+                       bool anyvisible,
+                       BlockNumber start_blockno,
+                       BlockNumber end_blockno,
+                       IndexBuildCallback callback,
+                       void *callback_state,
+                       TableScanDesc scan);
+</programlisting>
+   API to perform the table scan with bounded range specified by the caller
+   and insert the satisfied records into the index using the provided callback
+   function pointer.
+  </para>
+  
+    <para>
+<programlisting>
+void
+index_validate_scan (Relation heapRelation,
+                   Relation indexRelation,
+                   IndexInfo *indexInfo,
+                   Snapshot snapshot,
+                   struct ValidateIndexState *state);
+</programlisting>
+   API to perform the table scan and insert the satisfied records into the index.
+   This API is similar like <function>index_build_range_scan</function>. This 
+   is used in the scenario of concurrent index build.
+  </para>
+  
+ </sect2>
+ 
+ <sect2>
+  <title>Table scanning</title>
+  
+  <para>
+  </para>
+ </sect2>
+ 
+ <sect2>
+  <title>Table insert/update/delete</title>
+
+  <para>
+  </para>
+  </sect2>
+ 
+ <sect2>
+  <title>Table locking</title>
+
+  <para>
+  </para>
+  </sect2>
+ 
+ <sect2>
+  <title>Table vacuum</title>
+
+  <para>
+  </para>
+ </sect2>
+ 
+ <sect2>
+  <title>Table fetch</title>
+
+  <para>
+  </para>
+ </sect2>
+ 
+ </sect1> 
 </chapter>
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 0179deea2e..f0c8037bbc 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -587,8 +587,9 @@
    The catalog <structname>pg_am</structname> stores information about
    relation access methods.  There is one row for each access method supported
    by the system.
-   Currently, only indexes have access methods.  The requirements for index
-   access methods are discussed in detail in <xref linkend="indexam"/>.
+   Currently, only <literal>INDEX</literal> and <literal>TABLE</literal> have
+   access methods.  The requirements for access methods are discussed in detail
+   in <xref linkend="am"/>.
   </para>
 
   <table>
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f11b8f724c..8765d7c57c 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -6585,6 +6585,30 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-default-table-access-method" xreflabel="default_table_access_method">
+      <term><varname>default_table_access_method</varname> (<type>string</type>)
+      <indexterm>
+       <primary><varname>default_table_access_method</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        This variable specifies the default table access method using which to create
+        objects (tables and materialized views) when a <command>CREATE</command> command does
+        not explicitly specify a access method.
+       </para>
+
+       <para>
+        The value is either the name of a table access method, or an empty string
+        to specify using the default table access method of the current database.
+        If the value does not match the name of any existing table access methods,
+        <productname>PostgreSQL</productname> will automatically use the default
+        table access method of the current database.
+       </para>
+
+      </listitem>
+     </varlistentry>
+     
      <varlistentry id="guc-default-tablespace" xreflabel="default_tablespace">
       <term><varname>default_tablespace</varname> (<type>string</type>)
       <indexterm>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 48ac14a838..99a6496502 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -90,7 +90,7 @@
 <!ENTITY gin        SYSTEM "gin.sgml">
 <!ENTITY brin       SYSTEM "brin.sgml">
 <!ENTITY planstats    SYSTEM "planstats.sgml">
-<!ENTITY indexam    SYSTEM "indexam.sgml">
+<!ENTITY am         SYSTEM "am.sgml">
 <!ENTITY nls        SYSTEM "nls.sgml">
 <!ENTITY plhandler  SYSTEM "plhandler.sgml">
 <!ENTITY fdwhandler SYSTEM "fdwhandler.sgml">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 0070603fc3..3e66ae9c8a 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -251,7 +251,7 @@
   &tablesample-method;
   &custom-scan;
   &geqo;
-  &indexam;
+  &am;
   &generic-wal;
   &btree;
   &gist;
diff --git a/doc/src/sgml/ref/create_access_method.sgml b/doc/src/sgml/ref/create_access_method.sgml
index 851c5e63be..256914022a 100644
--- a/doc/src/sgml/ref/create_access_method.sgml
+++ b/doc/src/sgml/ref/create_access_method.sgml
@@ -61,7 +61,8 @@ CREATE ACCESS METHOD <replaceable class="parameter">name</replaceable>
     <listitem>
      <para>
       This clause specifies the type of access method to define.
-      Only <literal>INDEX</literal> is supported at present.
+      Only <literal>INDEX</literal> and <literal>TABLE</literal>
+      are supported at present.
      </para>
     </listitem>
    </varlistentry>
@@ -76,9 +77,12 @@ CREATE ACCESS METHOD <replaceable class="parameter">name</replaceable>
       declared to take a single argument of type <type>internal</type>,
       and its return type depends on the type of access method;
       for <literal>INDEX</literal> access methods, it must
-      be <type>index_am_handler</type>.  The C-level API that the handler
-      function must implement varies depending on the type of access method.
-      The index access method API is described in <xref linkend="indexam"/>.
+      be <type>index_am_handler</type> and for <literal>TABLE</literal>
+      access methods, it must be <type>table_am_handler</type>.
+      The C-level API that the handler function must implement varies
+      depending on the type of access method. The index access method API
+      is described in <xref linkend="index-access-methods"/> and the table access method
+      API is described in <xref linkend="table-access-methods"/>.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index 10428f8ff0..87e0f01ab2 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -29,6 +29,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 ] )
 [ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ]
 [ PARTITION BY { RANGE | LIST | HASH } ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ COLLATE <replaceable class="parameter">collation</replaceable> ] [ <replaceable class="parameter">opclass</replaceable> ] [, ... ] ) ]
+[ USING <replaceable class="parameter">method</replaceable> ]
 [ WITH ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
 [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
 [ TABLESPACE <replaceable class="parameter">tablespace_name</replaceable> ]
@@ -40,6 +41,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     [, ... ]
 ) ]
 [ PARTITION BY { RANGE | LIST | HASH } ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ COLLATE <replaceable class="parameter">collation</replaceable> ] [ <replaceable class="parameter">opclass</replaceable> ] [, ... ] ) ]
+[ USING <replaceable class="parameter">method</replaceable> ]
 [ WITH ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
 [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
 [ TABLESPACE <replaceable class="parameter">tablespace_name</replaceable> ]
@@ -51,6 +53,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     [, ... ]
 ) ] { FOR VALUES <replaceable class="parameter">partition_bound_spec</replaceable> | DEFAULT }
 [ PARTITION BY { RANGE | LIST | HASH } ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ COLLATE <replaceable class="parameter">collation</replaceable> ] [ <replaceable class="parameter">opclass</replaceable> ] [, ... ] ) ]
+[ USING <replaceable class="parameter">method</replaceable> ]
 [ WITH ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
 [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
 [ TABLESPACE <replaceable class="parameter">tablespace_name</replaceable> ]
@@ -955,7 +958,7 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
 
      <para>
       The access method must support <literal>amgettuple</literal> (see <xref
-      linkend="indexam"/>); at present this means <acronym>GIN</acronym>
+      linkend="index-access-methods"/>); at present this means <acronym>GIN</acronym>
       cannot be used.  Although it's allowed, there is little point in using
       B-tree or hash indexes with an exclusion constraint, because this
       does nothing that an ordinary unique constraint doesn't do better.
@@ -1138,6 +1141,19 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>USING <replaceable class="parameter">method</replaceable></literal></term>
+    <listitem>
+     <para>
+      This clause specifies optional access method for the new table;
+      see <xref linkend="table-access-methods"/> for more information.
+      If this option is not specified, then the default table access method
+      is chosen for the new table. see <xref linkend="guc-default-table-access-method"/>
+      for more information.
+     </para>
+    </listitem>
+   </varlistentry>
+   
    <varlistentry>
     <term><literal>WITH ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
diff --git a/doc/src/sgml/ref/create_table_as.sgml b/doc/src/sgml/ref/create_table_as.sgml
index 527138e787..2acf52d2f5 100644
--- a/doc/src/sgml/ref/create_table_as.sgml
+++ b/doc/src/sgml/ref/create_table_as.sgml
@@ -23,6 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable>table_name</replaceable>
     [ (<replaceable>column_name</replaceable> [, ...] ) ]
+    [ USING <replaceable class="parameter">method</replaceable> ]
     [ WITH ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]
     [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
     [ TABLESPACE <replaceable class="parameter">tablespace_name</replaceable> ]
@@ -120,6 +121,19 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>USING <replaceable class="parameter">method</replaceable></literal></term>
+    <listitem>
+     <para>
+      This clause specifies optional access method for the new table;
+      see <xref linkend="table-access-methods"/> for more information.
+      If this option is not specified, then the default table access method
+      is chosen for the new table. see <xref linkend="guc-default-table-access-method"/>
+      for more information.
+     </para>
+    </listitem>
+   </varlistentry>
+   
    <varlistentry>
     <term><literal>WITH ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term>
     <listitem>
diff --git a/doc/src/sgml/release-9.6.sgml b/doc/src/sgml/release-9.6.sgml
index acb6a88b31..68c79db4b5 100644
--- a/doc/src/sgml/release-9.6.sgml
+++ b/doc/src/sgml/release-9.6.sgml
@@ -10081,7 +10081,7 @@ This commit is also listed under libpq and PL/pgSQL
 2016-08-13 [ed0097e4f] Add SQL-accessible functions for inspecting index AM pro
 -->
        <para>
-        Restructure <link linkend="indexam">index access
+        Restructure <link linkend="index-access-methods">index access
         method <acronym>API</acronym></link> to hide most of it at
         the <application>C</application> level (Alexander Korotkov, Andrew Gierth)
        </para>
diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
index 9446f8b836..4fa821160c 100644
--- a/doc/src/sgml/xindex.sgml
+++ b/doc/src/sgml/xindex.sgml
@@ -36,7 +36,7 @@
    described in <classname>pg_am</classname>.  It is possible to add a
    new index access method by writing the necessary code and
    then creating an entry in <classname>pg_am</classname> &mdash; but that is
-   beyond the scope of this chapter (see <xref linkend="indexam"/>).
+   beyond the scope of this chapter (see <xref linkend="am"/>).
   </para>
 
   <para>
-- 
2.18.0.windows.1

