aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_relation.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2017-03-08 12:39:37 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2017-03-08 12:40:26 -0300
commitfcec6caafa2346b6c9d3ad5065e417733bd63cd9 (patch)
tree5a239cd7a7032d1b8dc8a4b558cc7eb740cde87f /src/backend/parser/parse_relation.c
parent270d7dd8a5a7128fc2b859f3bf95e2c1fb45be79 (diff)
downloadpostgresql-fcec6caafa2346b6c9d3ad5065e417733bd63cd9.tar.gz
postgresql-fcec6caafa2346b6c9d3ad5065e417733bd63cd9.zip
Support XMLTABLE query expression
XMLTABLE is defined by the SQL/XML standard as a feature that allows turning XML-formatted data into relational form, so that it can be used as a <table primary> in the FROM clause of a query. This new construct provides significant simplicity and performance benefit for XML data processing; what in a client-side custom implementation was reported to take 20 minutes can be executed in 400ms using XMLTABLE. (The same functionality was said to take 10 seconds using nested PostgreSQL XPath function calls, and 5 seconds using XMLReader under PL/Python). The implemented syntax deviates slightly from what the standard requires. First, the standard indicates that the PASSING clause is optional and that multiple XML input documents may be given to it; we make it mandatory and accept a single document only. Second, we don't currently support a default namespace to be specified. This implementation relies on a new executor node based on a hardcoded method table. (Because the grammar is fixed, there is no extensibility in the current approach; further constructs can be implemented on top of this such as JSON_TABLE, but they require changes to core code.) Author: Pavel Stehule, Álvaro Herrera Extensively reviewed by: Craig Ringer Discussion: https://postgr.es/m/CAFj8pRAgfzMD-LoSmnMGybD0WsEznLHWap8DO79+-GTRAPR4qA@mail.gmail.com
Diffstat (limited to 'src/backend/parser/parse_relation.c')
-rw-r--r--src/backend/parser/parse_relation.c79
1 files changed, 76 insertions, 3 deletions
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index cf69533b53d..2eea258d28d 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -1628,6 +1628,69 @@ addRangeTableEntryForFunction(ParseState *pstate,
}
/*
+ * Add an entry for a table function to the pstate's range table (p_rtable).
+ *
+ * This is much like addRangeTableEntry() except that it makes a tablefunc RTE.
+ */
+RangeTblEntry *
+addRangeTableEntryForTableFunc(ParseState *pstate,
+ TableFunc *tf,
+ Alias *alias,
+ bool lateral,
+ bool inFromCl)
+{
+ RangeTblEntry *rte = makeNode(RangeTblEntry);
+ char *refname = alias ? alias->aliasname : pstrdup("xmltable");
+ Alias *eref;
+ int numaliases;
+
+ Assert(pstate != NULL);
+
+ rte->rtekind = RTE_TABLEFUNC;
+ rte->relid = InvalidOid;
+ rte->subquery = NULL;
+ rte->tablefunc = tf;
+ rte->coltypes = tf->coltypes;
+ rte->coltypmods = tf->coltypmods;
+ rte->colcollations = tf->colcollations;
+ rte->alias = alias;
+
+ eref = alias ? copyObject(alias) : makeAlias(refname, NIL);
+ numaliases = list_length(eref->colnames);
+
+ /* fill in any unspecified alias columns */
+ if (numaliases < list_length(tf->colnames))
+ eref->colnames = list_concat(eref->colnames,
+ list_copy_tail(tf->colnames, numaliases));
+
+ rte->eref = eref;
+
+ /*
+ * Set flags and access permissions.
+ *
+ * Tablefuncs are never checked for access rights (at least, not by the
+ * RTE permissions mechanism).
+ */
+ rte->lateral = lateral;
+ rte->inh = false; /* never true for tablefunc RTEs */
+ rte->inFromCl = inFromCl;
+
+ rte->requiredPerms = 0;
+ rte->checkAsUser = InvalidOid;
+ rte->selectedCols = NULL;
+ rte->insertedCols = NULL;
+ rte->updatedCols = NULL;
+
+ /*
+ * Add completed RTE to pstate's range table list, but not to join list
+ * nor namespace --- caller must do that if appropriate.
+ */
+ pstate->p_rtable = lappend(pstate->p_rtable, rte);
+
+ return rte;
+}
+
+/*
* Add an entry for a VALUES list to the pstate's range table (p_rtable).
*
* This is much like addRangeTableEntry() except that it makes a values RTE.
@@ -2226,10 +2289,11 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
}
}
break;
+ case RTE_TABLEFUNC:
case RTE_VALUES:
case RTE_CTE:
{
- /* Values or CTE RTE */
+ /* Tablefunc, Values or CTE RTE */
ListCell *aliasp_item = list_head(rte->eref->colnames);
ListCell *lct;
ListCell *lcm;
@@ -2638,10 +2702,14 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
*varcollid = exprCollation(aliasvar);
}
break;
+ case RTE_TABLEFUNC:
case RTE_VALUES:
case RTE_CTE:
{
- /* VALUES or CTE RTE --- get type info from lists in the RTE */
+ /*
+ * tablefunc, VALUES or CTE RTE --- get type info from lists
+ * in the RTE
+ */
Assert(attnum > 0 && attnum <= list_length(rte->coltypes));
*vartype = list_nth_oid(rte->coltypes, attnum - 1);
*vartypmod = list_nth_int(rte->coltypmods, attnum - 1);
@@ -2684,9 +2752,14 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
}
break;
case RTE_SUBQUERY:
+ case RTE_TABLEFUNC:
case RTE_VALUES:
case RTE_CTE:
- /* Subselect, Values, CTE RTEs never have dropped columns */
+
+ /*
+ * Subselect, Table Functions, Values, CTE RTEs never have dropped
+ * columns
+ */
result = false;
break;
case RTE_JOIN: