On Mon, Oct 9, 2017 at 10:43 PM, Thomas Munro
<[email protected]> wrote:
>
> I suppose we could consider moving the schemaname check into
> getRTEForSpecialRelationType(), since otherwise both callers need to
> do that (and as you discovered, one forgot).
Thanks for the feedback. That was my first idea, but I assumed there
could be future use for this function on qualified RangeVar if it
wasn't done this way.
I agree it'd be much safer, so v2 attached, check moved in
getRTEForSpecialRelationType().
diff --git a/src/backend/parser/parse_clause.c
b/src/backend/parser/parse_clause.c
index 9ff80b8b40..255f485494 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -184,8 +184,10 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
RangeTblEntry *rte;
int rtindex;
- /* So far special relations are immutable; so they cannot be targets. */
+ /* Check if it's a CTE or tuplestore reference */
rte = getRTEForSpecialRelationTypes(pstate, relation);
+
+ /* So far special relations are immutable; so they cannot be targets. */
if (rte != NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1072,6 +1074,12 @@ transformRangeTableSample(ParseState *pstate,
RangeTableSample *rts)
}
+/*
+ * getRTEForSpecialRelationTypes
+ *
+ * If given RangeVar if a CTE reference or an EphemeralNamedRelation, return
+ * the transformed RangeVar otherwise return NULL
+ */
static RangeTblEntry *
getRTEForSpecialRelationTypes(ParseState *pstate, RangeVar *rv)
{
@@ -1079,6 +1087,13 @@ getRTEForSpecialRelationTypes(ParseState *pstate,
RangeVar *rv)
Index levelsup;
RangeTblEntry *rte = NULL;
+ /*
+ * if it is a qualified name, it can't be a CTE or tuplestore
+ * reference
+ */
+ if (rv->schemaname)
+ return NULL;
+
cte = scanNameSpaceForCTE(pstate, rv->relname, &levelsup);
if (cte)
rte = transformCTEReference(pstate, rv, cte, levelsup);
@@ -1119,15 +1134,11 @@ transformFromClauseItem(ParseState *pstate, Node *n,
/* Plain relation reference, or perhaps a CTE reference */
RangeVar *rv = (RangeVar *) n;
RangeTblRef *rtr;
- RangeTblEntry *rte = NULL;
+ RangeTblEntry *rte;
int rtindex;
- /*
- * if it is an unqualified name, it might be a CTE or tuplestore
- * reference
- */
- if (!rv->schemaname)
- rte = getRTEForSpecialRelationTypes(pstate, rv);
+ /* Check if it's a CTE or tuplestore reference */
+ rte = getRTEForSpecialRelationTypes(pstate, rv);
/* if not found above, must be a table reference */
if (!rte)
diff --git a/src/test/regress/expected/with.out
b/src/test/regress/expected/with.out
index c32a490580..53ea9991b2 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -2275,3 +2275,7 @@ with ordinality as (select 1 as x) select * from
ordinality;
-- check sane response to attempt to modify CTE relation
WITH d AS (SELECT 42) INSERT INTO d VALUES (1);
ERROR: relation "d" cannot be the target of a modifying statement
+-- check qualified relation name doesn't conflict with CTE name
+CREATE TABLE public.self (id integer);
+WITH self AS (SELECT 42) INSERT INTO public.self SELECT * from self;
+DROP TABLE public.self;
diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql
index 8ae5184d0f..17f32c3c87 100644
--- a/src/test/regress/sql/with.sql
+++ b/src/test/regress/sql/with.sql
@@ -1031,3 +1031,8 @@ with ordinality as (select 1 as x) select * from
ordinality;
-- check sane response to attempt to modify CTE relation
WITH d AS (SELECT 42) INSERT INTO d VALUES (1);
+
+-- check qualified relation name doesn't conflict with CTE name
+CREATE TABLE public.self (id integer);
+WITH self AS (SELECT 42) INSERT INTO public.self SELECT * from self;
+DROP TABLE public.self;
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers