]> granicus.if.org Git - postgresql/commitdiff
Behave correctly if INSERT ... VALUES is decorated with additional clauses.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 3 Oct 2010 00:02:27 +0000 (20:02 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 3 Oct 2010 00:02:27 +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 0a93ec70b0c6a0c4d31bdd2f1f2f8ccd1ba22807..21342e8a9d7f5535ae3a5a016d3c122d0229491e 100644 (file)
@@ -347,8 +347,17 @@ 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, FOR UPDATE, or WITH 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 ||
+                                                                         selectStmt->withClause != NULL));
 
        /*
         * If a non-nil rangetable/namespace was passed in, and we are doing