diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 97ef618..ce02af9 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -214,6 +214,16 @@
      </row>
 
      <row>
+      <entry><link linkend="catalog-pg-partition"><structname>pg_partition</structname></link></entry>
+      <entry>information about partitions, including partition boundary</entry>
+     </row>
+
+     <row>
+      <entry><link linkend="catalog-pg-partitioned-rel"><structname>pg_partitioned_rel</structname></link></entry>
+      <entry>information about partitioned tables, including the partition key</entry>
+     </row>
+
+     <row>
       <entry><link linkend="catalog-pg-pltemplate"><structname>pg_pltemplate</structname></link></entry>
       <entry>template data for procedural languages</entry>
      </row>
@@ -4629,6 +4639,161 @@
 
  </sect1>
 
+ <sect1 id="catalog-pg-partition">
+  <title><structname>pg_partition</structname></title>
+
+  <indexterm zone="catalog-pg-partition">
+   <primary>pg_partition</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_partition</structname> stores
+   information about partitions of partitioned tables.
+  </para>
+
+  <table>
+   <title><structname>pg_partition</> Columns</title>
+
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+
+     <row>
+      <entry><structfield>partrelid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the <structname>pg_class</> entry for this partition</entry>
+     </row>
+
+     <row>
+      <entry><structfield>partparent</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the partitioned table this partition is part of</entry>
+     </row>
+
+     <row>
+      <entry><structfield>partlistvals</structfield></entry>
+      <entry><type>anyarray</type></entry>
+      <entry></entry>
+      <entry>For partitions of a list partitioned table, list of values assigned to this partition</entry>
+     </row>
+
+     <row>
+      <entry><structfield>partrangemaxs</structfield></entry>
+      <entry><type>anyarray</type></entry>
+      <entry></entry>
+      <entry>For partitions of a range partitioned table, array of maximum values per partition key column</entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect1>
+
+ <sect1 id="catalog-pg-partitioned-rel">
+  <title><structname>pg_partitioned_rel</structname></title>
+
+  <indexterm zone="catalog-pg-partitioned-rel">
+   <primary>pg_partitioned_rel</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_partitioned</structname> stores
+   information about partition key of partitioned tables.
+  </para>
+
+  <table>
+   <title><structname>pg_partitioned_rel</> Columns</title>
+
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+
+     <row>
+      <entry><structfield>partrelid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the <structname>pg_class</> entry for this partitioned table</entry>
+     </row>
+
+     <row>
+      <entry><structfield>partstrat</structfield></entry>
+      <entry><type>char</type></entry>
+      <entry></entry>
+      <entry>
+       Partitioning strategy (method); <literal>l</> = list partitioned table,
+       <literal>r</> = range partitioned table
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>partnatts</structfield></entry>
+      <entry><type>int2</type></entry>
+      <entry></entry>
+      <entry>The number of columns in partition key</entry>
+     </row>
+
+     <row>
+      <entry><structfield>partkey</structfield></entry>
+      <entry><type>int2vector</type></entry>
+      <entry><literal><link linkend="catalog-pg-attribute"><structname>pg_attribute</structname></link>.attnum</literal></entry>
+      <entry>
+       This is an array of <structfield>partnatts</structfield> values that
+       correspond to table columns used as partition key.  For example, a value
+       of <literal>1 3</literal> would mean that the first and the third table
+       columns make up the partition key.  A zero in this array indicates that the
+       corresponding partition key column is an expression over the table columns,
+       rather than a simple column reference.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>partclass</structfield></entry>
+      <entry><type>oidvector</type></entry>
+      <entry><literal><link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link>.oid</literal></entry>
+      <entry>
+       For each column in the partition key, this contains the OID of
+       the operator class to use.  See
+       <link linkend="catalog-pg-opclass"><structname>pg_opclass</structname></link> for details.
+      </entry>
+     </row>
+
+     <row>
+      <entry><structfield>partexprs</structfield></entry>
+      <entry><type>pg_node_tree</type></entry>
+      <entry></entry>
+      <entry>
+       Expression trees (in <function>nodeToString()</function>
+       representation) for partition key columns that are not simple column
+       references.  This is a list with one element for each zero
+       entry in <structfield>partkey</>.  Null if all partition key columns
+       are simple references.
+      </entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+
+ </sect1>
 
  <sect1 id="catalog-pg-pltemplate">
   <title><structname>pg_pltemplate</structname></title>
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index aca40f5..07b3000 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -77,12 +77,23 @@ ALTER TABLE ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable>
     NOT OF
     OWNER TO { <replaceable class="PARAMETER">new_owner</replaceable> | CURRENT_USER | SESSION_USER }
     REPLICA IDENTITY { DEFAULT | USING INDEX <replaceable class="PARAMETER">index_name</replaceable> | FULL | NOTHING }
+    ATTACH PARTITION <replaceable class="PARAMETER">partition_name</replaceable> FOR VALUES { <replaceable class="PARAMETER">list_partition_values</replaceable> | <replaceable class="PARAMETER">range_partition_values</replaceable> } USING [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable>
+    DETACH PARTITION <replaceable class="PARAMETER">partition_name</replaceable> [ USING [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> ]
 
 <phrase>and <replaceable class="PARAMETER">table_constraint_using_index</replaceable> is:</phrase>
 
     [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
     { UNIQUE | PRIMARY KEY } USING INDEX <replaceable class="PARAMETER">index_name</replaceable>
     [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
+
+<phrase>and <replaceable class="PARAMETER">list_partition_values</replaceable> is:</phrase>
+
+[ IN ] ( { <replaceable class="PARAMETER">expression</replaceable> } [, ...] )
+
+<phrase>and <replaceable class="PARAMETER">range_partition_values</replaceable> is:</phrase>
+
+LESS THAN ( { <replaceable class="PARAMETER">expression</replaceable> } [, ...] )
+
 </synopsis>
  </refsynopsisdiv>
 
@@ -704,6 +715,32 @@ ALTER TABLE ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable>
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+   <term><literal>ATTACH PARTITION <replaceable class="PARAMETER">partition_name</replaceable> FOR VALUES { <replaceable class="PARAMETER">list_partition_values</replaceable> | <replaceable class="PARAMETER">range_partition_values</replaceable> } USING [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable></literal></term>
+    <listitem>
+     <para>
+      This form attaches a table as partition of the target table (presumably
+      partitioned.) To be attached as a partition, the source table must
+      already contain all the same columns as the parent.  The columns must
+      have matching data types, and if they have <literal>NOT NULL</literal>
+      constraints in the target table then they must also have <literal>
+      NOT NULL</literal> constraints in the source table. The table is renamed
+      to the specified partition name. [Note: this command is currently
+      unimplemented.]
+     </para>
+    </listitem>
+   </varlistentry> 
+
+   <varlistentry>
+   <term><literal>DETACH PARTITION <replaceable class="PARAMETER">partition_name</replaceable> [ USING [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> ] </literal></term>
+    <listitem>
+     <para>
+      This form detaches a partition from the target table (presumably
+      partitioned.) The resulting table can optionally have a different
+      name after being detached.
+     </para>
+    </listitem>
+   </varlistentry> 
   </variablelist>
   </para>
 
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index a2d0b0c..2fa7bc8 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -28,6 +28,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     [, ... ]
 ] )
 [ INHERITS ( <replaceable>parent_table</replaceable> [, ... ] ) ]
+[ PARTITION BY {RANGE | LIST} ON ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ <replaceable class="parameter">opclass</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> ]
@@ -42,6 +43,13 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
 [ TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable> ]
 
+CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] <replaceable class="PARAMETER">table_name</replaceable>
+    PARTITION OF <replaceable class="PARAMETER">table_name</replaceable>
+    FOR VALUES { <replaceable class="PARAMETER">list_partition_values</replaceable> | <replaceable class="PARAMETER">range_partition_values</replaceable> }
+[ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
+[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
+[ TABLESPACE <replaceable class="PARAMETER">tablespace_name</replaceable> ]
+
 <phrase>where <replaceable class="PARAMETER">column_constraint</replaceable> is:</phrase>
 
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
@@ -70,6 +78,14 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
 
 { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | ALL }
 
+<phrase>and <replaceable class="PARAMETER">list_partition_values</replaceable> is:</phrase>
+
+[ IN ] ( { <replaceable class="PARAMETER">expression</replaceable> } [, ...] )
+
+<phrase>and <replaceable class="PARAMETER">range_partition_values</replaceable> is:</phrase>
+
+LESS THAN ( { <replaceable class="PARAMETER">expression</replaceable> } [, ...] )
+
 <phrase><replaceable class="PARAMETER">index_parameters</replaceable> in <literal>UNIQUE</literal>, <literal>PRIMARY KEY</literal>, and <literal>EXCLUDE</literal> constraints are:</phrase>
 
 [ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
@@ -230,6 +246,40 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
    </varlistentry>
 
    <varlistentry>
+    <term><literal>PARTITION OF <replaceable class="PARAMETER">table_name</replaceable> FOR VALUES { <replaceable class="PARAMETER">list_partition_values</replaceable> | <replaceable class="PARAMETER">range_partition_values</replaceable> }</literal></term>
+    <listitem>
+     <para>
+      Creates the table as a <firstterm>partition</firstterm> of the
+      specified partitioned table.
+     </para>
+
+     <para>
+      When a table is created as partition, the data types of the
+      columns, constraints are determined by the underlying partitioned
+      table and are not specified by the <literal>CREATE TABLE</literal>
+      command nor can they be added or altered after the fact using
+      ALTER TABLE. But the <literal>CREATE TABLE</literal> command
+      command can specify table storage parameters and tablespace for the
+      partition (and can be altered after the fact). The <literal>
+      FOR VALUES</literal> specification describes partition bounds,
+      that is, either a list of values or of maximum values of partition
+      key columns for list partitions and range partitions, respectively.
+     </para>
+
+     <para>
+      Care must be taken to specify correct values for the bounds.
+      Specifying bounds such that new partition overlaps with some existing
+      partition results in error. Rules for whether such overlaps occurs
+      are different based on the partitioning method used. For list
+      bounds, make sure that the new partition's list of values does
+      not contain any values already present in some existing partition's
+      list. For range bounds, make sure that the new partition's rangemax
+      value is greater than the last existing partition's rangemax.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
     <term><replaceable class="PARAMETER">column_name</replaceable></term>
     <listitem>
      <para>
@@ -314,6 +364,32 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
    </varlistentry>
 
    <varlistentry>
+    <term><literal>PARTITION BY {RANGE | LIST} ON ( { <replaceable class="parameter">column_name</replaceable> | ( <replaceable class="parameter">expression</replaceable> ) } [ <replaceable class="parameter">opclass</replaceable> ] [, ...] )</literal></term>
+    <listitem>
+     <para>
+      The optional <literal>PARTITION BY</> clause specifies a list
+      of columns (or expressions) to use as the partition key of table.
+      Currently, <literal>LIST</> and <literal>RANGE</> can be specified
+      as the partitioning method. Such a table (hereafter referred to as
+      partitioned table) is divided into sub-tables called partitions which
+      are created after the fact.
+     </para>
+
+     <para>
+      Scanning a partitioned table results in scanning its partitions
+      and appending the results. Rows inserted into a partitioned table
+      are mapped to and stored in a partition based on values of partition
+      key columns unless an appropriate partition has not been defined yet.
+     </para>
+
+     <para>
+      There are currently a number of limitations on constraints that
+      can be defined on partitioned tables as detailed elsewhere.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
     <term><literal>LIKE <replaceable>source_table</replaceable> [ <replaceable>like_option</replaceable> ... ]</literal></term>
     <listitem>
      <para>
@@ -498,6 +574,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       primary key constraint defined for the table.  (Otherwise it
       would just be the same constraint listed twice.)
      </para>
+
+     <para>
+      UNIQUE constraints are not supported on partitioned tables at the moment.
+     </para>
     </listitem>
    </varlistentry>
 
@@ -526,6 +606,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       different from other sets of columns named by any unique
       constraint defined for the same table.
      </para>
+
+     <para>
+      Primary key constraints are not supported on partitioned tables at the moment.
+     </para>
     </listitem>
    </varlistentry>
 
@@ -576,6 +660,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       exclusion constraint on a subset of the table; internally this creates a
       partial index. Note that parentheses are required around the predicate.
      </para>
+
+     <para>
+      Exclusion constraints are not supported on partitioned tables at the moment. 
+     </para>
     </listitem>
    </varlistentry>
 
@@ -699,6 +787,10 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
       associated with the foreign key constraint can be performed more
       efficiently.
      </para>
+
+     <para>
+      Partitioned tables cannot use the REFERENCES clause at the moment.
+     </para>
     </listitem>
    </varlistentry>
 
@@ -1119,7 +1211,9 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     <para>
      Unique constraints and primary keys are not inherited in the
      current implementation.  This makes the combination of
-     inheritance and unique constraints rather dysfunctional.
+     inheritance and unique constraints rather dysfunctional. As
+     noted before, they cannot be used with partitioned tables
+     either.
     </para>
 
     <para>
@@ -1341,6 +1435,76 @@ CREATE TABLE employees OF employee_type (
     salary WITH OPTIONS DEFAULT 1000
 );
 </programlisting></para>
+
+  <para>
+   Create a range partitioned table and partitions:
+<programlisting>
+CREATE TABLE employee (
+    name text,
+    age int NOT NULL
+)
+PARTITION BY RANGE ON (age);
+
+CREATE TABLE employees_less_than_30
+    PARTITION OF employee
+    FOR VALUES LESS THAN (30)
+    WITH (fillfactor=70)
+    TABLESPACE diskvol1;
+
+CREATE TABLE employees_between_30_and_40
+    PARTITION OF employee
+    FOR VALUES LESS THAN (40)
+    WITH (fillfactor=70)
+    TABLESPACE diskvol2;
+</programlisting></para>
+
+  <para>
+   Create a list partitioned table and partitions:
+<programlisting>
+CREATE TABLE store (
+    id int,
+    city text NOT NULL
+)
+PARTITION BY LIST ON (city);
+
+CREATE TABLE store_east
+    PARTITION OF store
+    FOR VALUES IN ('New York', 'Boston');
+
+CREATE TABLE store_west
+    PARTITION OF store
+    FOR VALUES ('San Fransisco', 'Seattle');
+</programlisting></para>
+
+  <para>
+   Create a multi-column range partitioned table and partitions:
+<programlisting>
+CREATE TABLE sales (
+    tos timestamp NOT NULL,
+    item text
+)
+PARTITION BY RANGE ON (extract(year from tos), extract(month from tos));
+
+CREATE TABLE sales_before_2015
+    PARTITION OF sales
+    FOR VALUES LESS THAN (2015, 1);
+
+CREATE TABLE sales_2015_q1
+    PARTITION OF sales
+    FOR VALUES LESS THAN (2015, 4);
+
+CREATE TABLE sales_2015_q2
+    PARTITION OF sales
+    FOR VALUES LESS THAN (2015, 7);
+
+CREATE TABLE sales_2015_q3
+    PARTITION OF sales
+    FOR VALUES LESS THAN (2015, 10);
+
+CREATE TABLE sales_2015_q4
+    PARTITION OF sales
+    FOR VALUES LESS THAN (2016, 1);
+</programlisting></para>
  </refsect1>
 
  <refsect1 id="SQL-CREATETABLE-compatibility">
@@ -1511,6 +1675,16 @@ CREATE TABLE employees OF employee_type (
     effect can be had using the OID feature.
    </para>
   </refsect2>
+
+  <refsect2>
+   <title>Partitioned Tables</title>
+
+   <para>
+    <literal>PARTITION BY</literal> and <literal>PARTITION OF</literal> (including
+    <literal>FOR VALUES</literal>) are <productname>PostgreSQL</productname>
+    extensions.
+   </para>
+  </refsect2>
  </refsect1>
 
 
