agora inbox for [email protected]
help / color / mirror / Atom feedFrom: amit <[email protected]>
Subject: [PATCH 2/9] psql and pg_dump support for partitioned tables.
Date: Tue, 12 Jul 2016 17:20:23 +0900
Takes care of both the partition key deparse stuff and the new relkind.
---
src/backend/utils/adt/ruleutils.c | 140 ++++++++++++++++++++++++++++
src/bin/pg_dump/pg_dump.c | 36 ++++++--
src/bin/pg_dump/pg_dump.h | 1 +
src/bin/psql/describe.c | 61 +++++++++---
src/bin/psql/tab-complete.c | 6 +-
src/include/catalog/pg_proc.h | 2 +
src/include/utils/builtins.h | 1 +
src/test/regress/expected/create_table.out | 26 +++++
src/test/regress/sql/create_table.sql | 13 +++
9 files changed, 260 insertions(+), 26 deletions(-)
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 8a81d7a..03be202 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -33,6 +33,7 @@
#include "catalog/pg_language.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
+#include "catalog/pg_partitioned_table.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_trigger.h"
#include "catalog/pg_type.h"
@@ -315,6 +316,7 @@ static char *pg_get_indexdef_worker(Oid indexrelid, int colno,
const Oid *excludeOps,
bool attrsOnly, bool showTblSpc,
int prettyFlags, bool missing_ok);
+static char *pg_get_partkeydef_worker(Oid relid, int prettyFlags);
static char *pg_get_constraintdef_worker(Oid constraintId, bool fullCommand,
int prettyFlags, bool missing_ok);
static text *pg_get_expr_worker(text *expr, Oid relid, const char *relname,
@@ -1389,6 +1391,144 @@ pg_get_indexdef_worker(Oid indexrelid, int colno,
return buf.data;
}
+/*
+ * pg_get_partkeydef
+ *
+ * Returns the partition key specification, ie, the following:
+ *
+ * PARTITION BY { RANGE | LIST } (column [ opclass_name ] [, ...])
+ */
+Datum
+pg_get_partkeydef(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ int prettyFlags;
+
+ prettyFlags = PRETTYFLAG_INDENT;
+ PG_RETURN_TEXT_P(string_to_text(pg_get_partkeydef_worker(relid,
+ prettyFlags)));
+}
+
+/*
+ * Internal workhorse to decompile a partition key definition.
+ */
+static char *
+pg_get_partkeydef_worker(Oid relid, int prettyFlags)
+{
+ Form_pg_partitioned_table form;
+ HeapTuple tuple;
+ oidvector *partclass;
+ List *partexprs;
+ ListCell *partexpr_item;
+ List *context;
+ Datum datum;
+ bool isnull;
+ StringInfoData buf;
+ int keyno;
+ char *str;
+ char *sep;
+
+ tuple = SearchSysCache1(PARTEDRELID, ObjectIdGetDatum(relid));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for partition key of %u", relid);
+
+ form = (Form_pg_partitioned_table) GETSTRUCT(tuple);
+
+ Assert(form->partrelid == relid);
+
+ /* Must get partclass, and partexprs the hard way */
+ datum = SysCacheGetAttr(PARTEDRELID, tuple,
+ Anum_pg_partitioned_table_partclass, &isnull);
+ Assert(!isnull);
+ partclass = (oidvector *) DatumGetPointer(datum);
+
+ /*
+ * Get the partition key expressions, if any. (NOTE: we do not use the
+ * relcache versions of the expressions, because we want to display
+ * non-const-folded expressions.)
+ */
+ if (!heap_attisnull(tuple, Anum_pg_partitioned_table_partexprbin))
+ {
+ Datum exprsDatum;
+ bool isnull;
+ char *exprsString;
+
+ exprsDatum = SysCacheGetAttr(PARTEDRELID, tuple,
+ Anum_pg_partitioned_table_partexprbin, &isnull);
+ Assert(!isnull);
+ exprsString = TextDatumGetCString(exprsDatum);
+ partexprs = (List *) stringToNode(exprsString);
+ pfree(exprsString);
+ }
+ else
+ partexprs = NIL;
+
+ partexpr_item = list_head(partexprs);
+ context = deparse_context_for(get_relation_name(relid), relid);
+
+ /*
+ * Start the partition key definition.
+ */
+ initStringInfo(&buf);
+
+ switch (form->partstrat)
+ {
+ case 'l':
+ appendStringInfo(&buf, "LIST");
+ break;
+ case 'r':
+ appendStringInfo(&buf, "RANGE");
+ break;
+ }
+
+ /*
+ * Report the partition key columns
+ */
+ appendStringInfo(&buf, " (");
+ sep = "";
+ for (keyno = 0; keyno < form->partnatts; keyno++)
+ {
+ AttrNumber attnum = form->partattrs.values[keyno];
+ Oid keycoltype;
+
+ appendStringInfoString(&buf, sep);
+ sep = ", ";
+ if (attnum != 0)
+ {
+ /* Simple partition key column */
+ char *attname;
+
+ attname = get_relid_attribute_name(relid, attnum);
+ appendStringInfoString(&buf, quote_identifier(attname));
+ keycoltype = get_atttype(relid, attnum);
+ }
+ else
+ {
+ /* partition key expression */
+ Node *partkey;
+
+ if (partexpr_item == NULL)
+ elog(ERROR, "too few entries in partexprs list");
+ partkey = (Node *) lfirst(partexpr_item);
+ partexpr_item = lnext(partexpr_item);
+ /* Deparse */
+ str = deparse_expression_pretty(partkey, context, false, false,
+ 0, 0);
+
+ appendStringInfoString(&buf, str);
+ keycoltype = exprType(partkey);
+ }
+
+ /* Add the operator class name, if not default */
+ get_opclass_name(partclass->values[keyno], keycoltype, &buf);
+ }
+ appendStringInfoChar(&buf, ')');
+
+ /* Clean up */
+ ReleaseSysCache(tuple);
+
+ return buf.data;
+}
/*
* pg_get_constraintdef
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 51b8a1a..854dddc 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -1253,9 +1253,10 @@ expand_table_name_patterns(Archive *fout,
"SELECT c.oid"
"\nFROM pg_catalog.pg_class c"
"\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"
- "\nWHERE c.relkind in ('%c', '%c', '%c', '%c', '%c')\n",
+ "\nWHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c')\n",
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
+ RELKIND_PARTITIONED_TABLE);
processSQLNamePattern(GetConnection(fout), query, cell->val, true,
false, "n.nspname", "c.relname", NULL,
"pg_catalog.pg_table_is_visible(c.oid)");
@@ -2125,6 +2126,9 @@ makeTableDataInfo(DumpOptions *dopt, TableInfo *tbinfo, bool oids)
/* Skip FOREIGN TABLEs (no data to dump) */
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
return;
+ /* Skip partitioned tables (data in partitions) */
+ if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
+ return;
/* Don't dump data in unlogged tables, if so requested */
if (tbinfo->relpersistence == RELPERSISTENCE_UNLOGGED &&
@@ -5211,6 +5215,7 @@ getTables(Archive *fout, int *numTables)
int i_reloftype;
int i_relpages;
int i_changed_acl;
+ int i_partkeydef;
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
@@ -5296,7 +5301,8 @@ getTables(Archive *fout, int *numTables)
"OR %s IS NOT NULL "
"OR %s IS NOT NULL"
"))"
- "AS changed_acl "
+ "AS changed_acl, "
+ "CASE WHEN c.relkind = 'P' THEN pg_catalog.pg_get_partkeydef(c.oid) ELSE NULL END AS partkeydef "
"FROM pg_class c "
"LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND "
@@ -5308,7 +5314,7 @@ getTables(Archive *fout, int *numTables)
"(c.oid = pip.objoid "
"AND pip.classoid = 'pg_class'::regclass "
"AND pip.objsubid = 0) "
- "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') "
+ "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c', '%c') "
"ORDER BY c.oid",
acl_subquery->data,
racl_subquery->data,
@@ -5322,7 +5328,8 @@ getTables(Archive *fout, int *numTables)
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
- RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE);
+ RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
+ RELKIND_PARTITIONED_TABLE);
destroyPQExpBuffer(acl_subquery);
destroyPQExpBuffer(racl_subquery);
@@ -5884,6 +5891,7 @@ getTables(Archive *fout, int *numTables)
i_toastreloptions = PQfnumber(res, "toast_reloptions");
i_reloftype = PQfnumber(res, "reloftype");
i_changed_acl = PQfnumber(res, "changed_acl");
+ i_partkeydef = PQfnumber(res, "partkeydef");
if (dopt->lockWaitTimeout && fout->remoteVersion >= 70300)
{
@@ -5954,6 +5962,7 @@ getTables(Archive *fout, int *numTables)
else
tblinfo[i].checkoption = pg_strdup(PQgetvalue(res, i, i_checkoption));
tblinfo[i].toast_reloptions = pg_strdup(PQgetvalue(res, i, i_toastreloptions));
+ tblinfo[i].partkeydef = pg_strdup(PQgetvalue(res, i, i_partkeydef));
/* other fields were zeroed above */
@@ -5998,7 +6007,9 @@ getTables(Archive *fout, int *numTables)
* We only need to lock the table for certain components; see
* pg_dump.h
*/
- if (tblinfo[i].dobj.dump && tblinfo[i].relkind == RELKIND_RELATION &&
+ if (tblinfo[i].dobj.dump &&
+ (tblinfo[i].relkind == RELKIND_RELATION ||
+ tblinfo->relkind == RELKIND_PARTITIONED_TABLE) &&
(tblinfo[i].dobj.dump & DUMP_COMPONENTS_REQUIRING_LOCK))
{
resetPQExpBuffer(query);
@@ -6100,7 +6111,10 @@ getInherits(Archive *fout, int *numInherits)
/* find all the inheritance information */
- appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits");
+ appendPQExpBufferStr(query,
+ "SELECT inhrelid, inhparent "
+ "FROM pg_inherits "
+ "WHERE inhparent NOT IN (SELECT oid FROM pg_class WHERE relkind = 'P')");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
@@ -15453,6 +15467,9 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBufferChar(q, ')');
}
+ if (tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
+ appendPQExpBuffer(q, "\nPARTITION BY %s", tbinfo->partkeydef);
+
if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
}
@@ -15513,6 +15530,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
*/
if (dopt->binary_upgrade &&
(tbinfo->relkind == RELKIND_RELATION ||
+ tbinfo->relkind == RELKIND_PARTITIONED_TABLE ||
tbinfo->relkind == RELKIND_FOREIGN_TABLE))
{
for (j = 0; j < tbinfo->numatts; j++)
@@ -15531,7 +15549,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendStringLiteralAH(q, fmtId(tbinfo->dobj.name), fout);
appendPQExpBufferStr(q, "::pg_catalog.regclass;\n");
- if (tbinfo->relkind == RELKIND_RELATION)
+ if (tbinfo->relkind == RELKIND_RELATION ||
+ tbinfo->relkind == RELKIND_PARTITIONED_TABLE)
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
fmtId(tbinfo->dobj.name));
else
@@ -15748,6 +15767,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
* dump properties we only have ALTER TABLE syntax for
*/
if ((tbinfo->relkind == RELKIND_RELATION ||
+ tbinfo->relkind == RELKIND_PARTITIONED_TABLE ||
tbinfo->relkind == RELKIND_MATVIEW) &&
tbinfo->relreplident != REPLICA_IDENTITY_DEFAULT)
{
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 2bfa2d9..0292859 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -310,6 +310,7 @@ typedef struct _tableInfo
bool *inhNotNull; /* true if NOT NULL is inherited */
struct _attrDefInfo **attrdefs; /* DEFAULT expressions */
struct _constraintInfo *checkexprs; /* CHECK constraints */
+ char *partkeydef; /* partition key definition */
/*
* Stuff computed only for dumpable tables.
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 6275a68..db6dc5c 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -861,6 +861,7 @@ permissionsList(const char *pattern)
" c.relname as \"%s\",\n"
" CASE c.relkind"
" WHEN 'r' THEN '%s'"
+ " WHEN 'P' THEN '%s'"
" WHEN 'v' THEN '%s'"
" WHEN 'm' THEN '%s'"
" WHEN 'S' THEN '%s'"
@@ -870,6 +871,7 @@ permissionsList(const char *pattern)
gettext_noop("Schema"),
gettext_noop("Name"),
gettext_noop("table"),
+ gettext_noop("table"),
gettext_noop("view"),
gettext_noop("materialized view"),
gettext_noop("sequence"),
@@ -920,7 +922,7 @@ permissionsList(const char *pattern)
appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
- "WHERE c.relkind IN ('r', 'v', 'm', 'S', 'f')\n");
+ "WHERE c.relkind IN ('r', 'v', 'm', 'S', 'f', 'P')\n");
/*
* Unless a schema pattern is specified, we suppress system and temp
@@ -1567,8 +1569,8 @@ describeOneTableDetails(const char *schemaname,
* types, and foreign tables (c.f. CommentObject() in comment.c).
*/
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' ||
- tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'f' || tableinfo.relkind == 'c')
+ tableinfo.relkind == 'm' || tableinfo.relkind == 'f' ||
+ tableinfo.relkind == 'c' || tableinfo.relkind == 'P')
appendPQExpBufferStr(&buf, ", pg_catalog.col_description(a.attrelid, a.attnum)");
}
@@ -1633,6 +1635,14 @@ describeOneTableDetails(const char *schemaname,
printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""),
schemaname, relationname);
break;
+ case 'P':
+ if (tableinfo.relpersistence == 'u')
+ printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""),
+ schemaname, relationname);
+ else
+ printfPQExpBuffer(&title, _("Table \"%s.%s\""),
+ schemaname, relationname);
+ break;
default:
/* untranslated unknown relkind */
printfPQExpBuffer(&title, "?%c? \"%s.%s\"",
@@ -1646,8 +1656,8 @@ describeOneTableDetails(const char *schemaname,
cols = 2;
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' ||
- tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'f' || tableinfo.relkind == 'c')
+ tableinfo.relkind == 'm' || tableinfo.relkind == 'f' ||
+ tableinfo.relkind == 'c' || tableinfo.relkind == 'P')
{
show_modifiers = true;
headers[cols++] = gettext_noop("Modifiers");
@@ -1667,12 +1677,12 @@ describeOneTableDetails(const char *schemaname,
{
headers[cols++] = gettext_noop("Storage");
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'f')
+ tableinfo.relkind == 'f' || tableinfo.relkind == 'P')
headers[cols++] = gettext_noop("Stats target");
/* Column comments, if the relkind supports this feature. */
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' ||
- tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'c' || tableinfo.relkind == 'f')
+ tableinfo.relkind == 'm' || tableinfo.relkind == 'c' ||
+ tableinfo.relkind == 'f' || tableinfo.relkind == 'P')
headers[cols++] = gettext_noop("Description");
}
@@ -1772,7 +1782,7 @@ describeOneTableDetails(const char *schemaname,
/* Statistics target, if the relkind supports this feature */
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'f')
+ tableinfo.relkind == 'f' || tableinfo.relkind == 'P')
{
printTableAddCell(&cont, PQgetvalue(res, i, firstvcol + 1),
false, false);
@@ -1780,14 +1790,33 @@ describeOneTableDetails(const char *schemaname,
/* Column comments, if the relkind supports this feature. */
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' ||
- tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'c' || tableinfo.relkind == 'f')
+ tableinfo.relkind == 'm' || tableinfo.relkind == 'c' ||
+ tableinfo.relkind == 'f' || tableinfo.relkind == 'P')
printTableAddCell(&cont, PQgetvalue(res, i, firstvcol + 2),
false, false);
}
}
/* Make footers */
+ if (tableinfo.relkind == 'P')
+ {
+ /* Get the partition key information */
+ PGresult *result;
+ char *partkeydef;
+
+ printfPQExpBuffer(&buf,
+ "SELECT pg_catalog.pg_get_partkeydef('%s'::pg_catalog.oid);",
+ oid);
+ result = PSQLexec(buf.data);
+ if (!result || PQntuples(result) != 1)
+ goto error_return;
+
+ partkeydef = PQgetvalue(result, 0, 0);
+ printfPQExpBuffer(&tmpbuf, _("Partition key: %s"), partkeydef);
+ printTableAddFooter(&cont, tmpbuf.data);
+ PQclear(result);
+ }
+
if (tableinfo.relkind == 'i')
{
/* Footer information about an index */
@@ -1926,7 +1955,7 @@ describeOneTableDetails(const char *schemaname,
PQclear(result);
}
else if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'f')
+ tableinfo.relkind == 'f' || tableinfo.relkind == 'P')
{
/* Footer information about a table */
PGresult *result = NULL;
@@ -2485,7 +2514,7 @@ describeOneTableDetails(const char *schemaname,
* Finish printing the footer information about a table.
*/
if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' ||
- tableinfo.relkind == 'f')
+ tableinfo.relkind == 'f' || tableinfo.relkind == 'P')
{
PGresult *result;
int tuples;
@@ -2696,7 +2725,7 @@ add_tablespace_footer(printTableContent *const cont, char relkind,
Oid tablespace, const bool newline)
{
/* relkinds for which we support tablespaces */
- if (relkind == 'r' || relkind == 'm' || relkind == 'i')
+ if (relkind == 'r' || relkind == 'm' || relkind == 'i' || relkind == 'P')
{
/*
* We ignore the database default tablespace so that users not using
@@ -3024,6 +3053,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
" c.relname as \"%s\",\n"
" CASE c.relkind"
" WHEN 'r' THEN '%s'"
+ " WHEN 'P' THEN '%s'"
" WHEN 'v' THEN '%s'"
" WHEN 'm' THEN '%s'"
" WHEN 'i' THEN '%s'"
@@ -3035,6 +3065,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
gettext_noop("Schema"),
gettext_noop("Name"),
gettext_noop("table"),
+ gettext_noop("table"),
gettext_noop("view"),
gettext_noop("materialized view"),
gettext_noop("index"),
@@ -3079,7 +3110,7 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN (");
if (showTables)
- appendPQExpBufferStr(&buf, "'r',");
+ appendPQExpBufferStr(&buf, "'r', 'P',");
if (showViews)
appendPQExpBufferStr(&buf, "'v',");
if (showMatViews)
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 50a45eb..8284a9c 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -427,7 +427,7 @@ static const SchemaQuery Query_for_list_of_tables = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
- "c.relkind IN ('r')",
+ "c.relkind IN ('r', 'P')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
@@ -458,7 +458,7 @@ static const SchemaQuery Query_for_list_of_updatables = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
- "c.relkind IN ('r', 'f', 'v')",
+ "c.relkind IN ('r', 'f', 'v', 'P')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
@@ -488,7 +488,7 @@ static const SchemaQuery Query_for_list_of_tsvmf = {
/* catname */
"pg_catalog.pg_class c",
/* selcondition */
- "c.relkind IN ('r', 'S', 'v', 'm', 'f')",
+ "c.relkind IN ('r', 'S', 'v', 'm', 'f', 'P')",
/* viscondition */
"pg_catalog.pg_table_is_visible(c.oid)",
/* namespace */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index e2d08ba..b45688b 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -1980,6 +1980,8 @@ DATA(insert OID = 1642 ( pg_get_userbyid PGNSP PGUID 12 1 0 0 0 f f f f t f
DESCR("role name by OID (with fallback)");
DATA(insert OID = 1643 ( pg_get_indexdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_indexdef _null_ _null_ _null_ ));
DESCR("index description");
+DATA(insert OID = 3352 ( pg_get_partkeydef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_partkeydef _null_ _null_ _null_ ));
+DESCR("partition key description");
DATA(insert OID = 1662 ( pg_get_triggerdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_triggerdef _null_ _null_ _null_ ));
DESCR("trigger description");
DATA(insert OID = 1387 ( pg_get_constraintdef PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 25 "26" _null_ _null_ _null_ _null_ _null_ pg_get_constraintdef _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 2ae212a..e800647 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -729,6 +729,7 @@ extern Datum pg_get_viewdef_wrap(PG_FUNCTION_ARGS);
extern Datum pg_get_viewdef_name(PG_FUNCTION_ARGS);
extern Datum pg_get_viewdef_name_ext(PG_FUNCTION_ARGS);
extern Datum pg_get_indexdef(PG_FUNCTION_ARGS);
+extern Datum pg_get_partkeydef(PG_FUNCTION_ARGS);
extern Datum pg_get_indexdef_ext(PG_FUNCTION_ARGS);
extern Datum pg_get_triggerdef(PG_FUNCTION_ARGS);
extern Datum pg_get_triggerdef_ext(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/create_table.out b/src/test/regress/expected/create_table.out
index 1394362..260ec34 100644
--- a/src/test/regress/expected/create_table.out
+++ b/src/test/regress/expected/create_table.out
@@ -407,3 +407,29 @@ CREATE TABLE no_inh_con_parted (
CONSTRAINT check_a CHECK (a > 0) NO INHERIT
) PARTITION BY RANGE (a);
ERROR: cannot add NO INHERIT constraint to partitioned table "no_inh_con_parted"
+-- Partition key in describe output
+CREATE TABLE describe_range_key (
+ a int,
+ b int
+) PARTITION BY RANGE ((a+b));
+\d describe_range_key
+Table "public.describe_range_key"
+ Column | Type | Modifiers
+--------+---------+-----------
+ a | integer |
+ b | integer |
+Partition key: RANGE ((a + b))
+
+CREATE TABLE describe_list_key (
+ a int,
+ b int
+) PARTITION BY LIST (a);
+\d describe_list_key
+Table "public.describe_list_key"
+ Column | Type | Modifiers
+--------+---------+-----------
+ a | integer |
+ b | integer |
+Partition key: LIST (a)
+
+DROP TABLE describe_range_key, describe_list_key;
diff --git a/src/test/regress/sql/create_table.sql b/src/test/regress/sql/create_table.sql
index d383f58..7a1f8de 100644
--- a/src/test/regress/sql/create_table.sql
+++ b/src/test/regress/sql/create_table.sql
@@ -401,3 +401,16 @@ CREATE TABLE no_inh_con_parted (
a int,
CONSTRAINT check_a CHECK (a > 0) NO INHERIT
) PARTITION BY RANGE (a);
+
+-- Partition key in describe output
+CREATE TABLE describe_range_key (
+ a int,
+ b int
+) PARTITION BY RANGE ((a+b));
+\d describe_range_key
+CREATE TABLE describe_list_key (
+ a int,
+ b int
+) PARTITION BY LIST (a);
+\d describe_list_key
+DROP TABLE describe_range_key, describe_list_key;
--
1.7.1
--------------C3235EE96C69D8DAE4DB543E
Content-Type: text/x-diff;
name="0003-Catalog-and-DDL-for-partitions-6.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="0003-Catalog-and-DDL-for-partitions-6.patch"
view thread (110+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [PATCH 2/9] psql and pg_dump support for partitioned tables.
In-Reply-To: <no-message-id-510392@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox