]> granicus.if.org Git - postgresql/commitdiff
Fix yet another bug in ON CONFLICT rule deparsing.
authorAndres Freund <andres@anarazel.de>
Sat, 23 May 2015 00:16:24 +0000 (02:16 +0200)
committerAndres Freund <andres@anarazel.de>
Sat, 23 May 2015 00:16:24 +0000 (02:16 +0200)
Expand testing of rule deparsing a good bit, it's evidently needed.

Author: Peter Geoghegan, Andres Freund
Discussion: CAM3SWZQmXxZhQC32QVEOTYfNXJBJ_Q2SDENL7BV14Cq-zL0FLg@mail.gmail.com

src/backend/utils/adt/ruleutils.c
src/test/regress/expected/rules.out
src/test/regress/sql/rules.sql

index 8cdef086a0bf2af1d8564e800a5c79540c4ee47c..0585251d8fed95adad2a91b3e94f269beb39ff3f 100644 (file)
@@ -5500,7 +5500,7 @@ get_insert_query_def(Query *query, deparse_context *context)
                                get_rule_expr(confl->arbiterWhere, context, false);
                        }
                }
-               else
+               else if (confl->constraint != InvalidOid)
                {
                        char   *constraint = get_constraint_name(confl->constraint);
 
index a2ed8fa7fa7176c1129194dcd4aeed69776e71f3..60c1f408fccd5e20ea3051bfd102ae19e951a559 100644 (file)
@@ -2811,14 +2811,26 @@ CREATE TABLE hat_data (
 );
 create unique index hat_data_unique_idx
   on hat_data (hat_name COLLATE "C" bpchar_pattern_ops);
--- okay
+-- DO NOTHING with ON CONFLICT
 CREATE RULE hat_nosert AS ON INSERT TO hats
     DO INSTEAD
     INSERT INTO hat_data VALUES (
            NEW.hat_name,
            NEW.hat_color)
         ON CONFLICT (hat_name COLLATE "C" bpchar_pattern_ops) WHERE hat_color = 'green'
-        DO NOTHING RETURNING *;
+        DO NOTHING
+        RETURNING *;
+SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
+                                         definition                                          
+---------------------------------------------------------------------------------------------
+ CREATE RULE hat_nosert AS                                                                  +
+     ON INSERT TO hats DO INSTEAD  INSERT INTO hat_data (hat_name, hat_color)               +
+   VALUES (new.hat_name, new.hat_color) ON CONFLICT(hat_name COLLATE "C" bpchar_pattern_ops)+
+   WHERE (hat_data.hat_color = 'green'::bpchar) DO NOTHING                                  +
+   RETURNING hat_data.hat_name,                                                             +
+     hat_data.hat_color;
+(1 row)
+
 -- Works (projects row)
 INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
   hat_name  | hat_color  
@@ -2845,6 +2857,34 @@ SELECT tablename, rulename, definition FROM pg_rules
 (1 row)
 
 DROP RULE hat_nosert ON hats;
+-- DO NOTHING without ON CONFLICT
+CREATE RULE hat_nosert_all AS ON INSERT TO hats
+    DO INSTEAD
+    INSERT INTO hat_data VALUES (
+           NEW.hat_name,
+           NEW.hat_color)
+        ON CONFLICT
+        DO NOTHING
+        RETURNING *;
+SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
+                                  definition                                  
+------------------------------------------------------------------------------
+ CREATE RULE hat_nosert_all AS                                               +
+     ON INSERT TO hats DO INSTEAD  INSERT INTO hat_data (hat_name, hat_color)+
+   VALUES (new.hat_name, new.hat_color) ON CONFLICT DO NOTHING               +
+   RETURNING hat_data.hat_name,                                              +
+     hat_data.hat_color;
+(1 row)
+
+DROP RULE hat_nosert_all ON hats;
+-- Works (does nothing)
+INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
+  hat_name  | hat_color  
+------------+------------
+ h7         | black     
+(1 row)
+
+-- DO UPDATE with a WHERE clause
 CREATE RULE hat_upsert AS ON INSERT TO hats
     DO INSTEAD
     INSERT INTO hat_data VALUES (
@@ -2855,6 +2895,17 @@ CREATE RULE hat_upsert AS ON INSERT TO hats
            SET hat_name = hat_data.hat_name, hat_color = excluded.hat_color
            WHERE excluded.hat_color <>  'forbidden'
         RETURNING *;
+SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
+                                                               definition                                                                
+-----------------------------------------------------------------------------------------------------------------------------------------
+ CREATE RULE hat_upsert AS                                                                                                              +
+     ON INSERT TO hats DO INSTEAD  INSERT INTO hat_data (hat_name, hat_color)                                                           +
+   VALUES (new.hat_name, new.hat_color) ON CONFLICT(hat_name) DO UPDATE SET hat_name = hat_data.hat_name, hat_color = excluded.hat_color+
+   WHERE (excluded.hat_color <> 'forbidden'::bpchar)                                                                                    +
+   RETURNING hat_data.hat_name,                                                                                                         +
+     hat_data.hat_color;
+(1 row)
+
 -- Works (does upsert)
 INSERT INTO hats VALUES ('h8', 'black') RETURNING *;
   hat_name  | hat_color  
index 1f9f7e69d2857dff7e94ab91c1ce7c0e77b2ef09..561e2fd29a5de0529f638d8e9bab4359b3898610 100644 (file)
@@ -1062,14 +1062,16 @@ CREATE TABLE hat_data (
 create unique index hat_data_unique_idx
   on hat_data (hat_name COLLATE "C" bpchar_pattern_ops);
 
--- okay
+-- DO NOTHING with ON CONFLICT
 CREATE RULE hat_nosert AS ON INSERT TO hats
     DO INSTEAD
     INSERT INTO hat_data VALUES (
            NEW.hat_name,
            NEW.hat_color)
         ON CONFLICT (hat_name COLLATE "C" bpchar_pattern_ops) WHERE hat_color = 'green'
-        DO NOTHING RETURNING *;
+        DO NOTHING
+        RETURNING *;
+SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
 
 -- Works (projects row)
 INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
@@ -1079,6 +1081,22 @@ SELECT tablename, rulename, definition FROM pg_rules
        WHERE tablename = 'hats';
 DROP RULE hat_nosert ON hats;
 
+-- DO NOTHING without ON CONFLICT
+CREATE RULE hat_nosert_all AS ON INSERT TO hats
+    DO INSTEAD
+    INSERT INTO hat_data VALUES (
+           NEW.hat_name,
+           NEW.hat_color)
+        ON CONFLICT
+        DO NOTHING
+        RETURNING *;
+SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
+DROP RULE hat_nosert_all ON hats;
+
+-- Works (does nothing)
+INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
+
+-- DO UPDATE with a WHERE clause
 CREATE RULE hat_upsert AS ON INSERT TO hats
     DO INSTEAD
     INSERT INTO hat_data VALUES (
@@ -1089,6 +1107,7 @@ CREATE RULE hat_upsert AS ON INSERT TO hats
            SET hat_name = hat_data.hat_name, hat_color = excluded.hat_color
            WHERE excluded.hat_color <>  'forbidden'
         RETURNING *;
+SELECT definition FROM pg_rules WHERE tablename = 'hats' ORDER BY rulename;
 
 -- Works (does upsert)
 INSERT INTO hats VALUES ('h8', 'black') RETURNING *;