]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Behave correctly if INSERT ... VALUES is decorated with additional clauses.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 3 Oct 2010 00:02:52 +0000 (20:02 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 3 Oct 2010 00:02:52 +0000 (20:02 -0400)
In versions 8.2 and up, the grammar allows attaching ORDER BY, LIMIT,
FOR UPDATE, or WITH to VALUES, and hence to INSERT ... VALUES.  But the
special-case code for VALUES in transformInsertStmt() wasn't expecting any
of those, and just ignored them, leading to unexpected results.  Rather
than complicate the special-case path, just ensure that the presence of any
of those clauses makes us treat the query as if it had a general SELECT.
Per report from Hitoshi Harada.

src/backend/parser/analyze.c

index 65de8610179765488304fa56e8c8dc5bb942a8c6..3ffa1b63c5d5e103cf8de1d20e0d317b6e3c986b 100644 (file)
@@ -604,8 +604,16 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
         * We have three cases to deal with: DEFAULT VALUES (selectStmt == NULL),
         * VALUES list, or general SELECT input.  We special-case VALUES, both for
         * efficiency and so we can handle DEFAULT specifications.
+        *
+        * The grammar allows attaching ORDER BY, LIMIT, or FOR UPDATE to a
+        * VALUES clause.  If we have any of those, treat it as a general SELECT;
+        * so it will work, but you can't use DEFAULT items together with those.
         */
-       isGeneralSelect = (selectStmt && selectStmt->valuesLists == NIL);
+       isGeneralSelect = (selectStmt && (selectStmt->valuesLists == NIL ||
+                                                                         selectStmt->sortClause != NIL ||
+                                                                         selectStmt->limitOffset != NULL ||
+                                                                         selectStmt->limitCount != NULL ||
+                                                                         selectStmt->lockingClause != NIL));
 
        /*
         * If a non-nil rangetable/namespace was passed in, and we are doing