@@ -2817,25 +2817,112 @@ CREATE RULE hat_upsert AS ON INSERT TO hats
2817
2817
INSERT INTO hat_data VALUES (
2818
2818
NEW.hat_name,
2819
2819
NEW.hat_color)
2820
- ON CONFLICT (hat_name) DO UPDATE SET hat_color = 'Orange' RETURNING *;
2820
+ ON CONFLICT (hat_name)
2821
+ DO UPDATE
2822
+ SET hat_name = hat_data.hat_name, hat_color = excluded.hat_color
2823
+ WHERE excluded.hat_color <> 'forbidden'
2824
+ RETURNING *;
2821
2825
-- Works (does upsert)
2822
- INSERT INTO hats VALUES ('h7', 'black') RETURNING *;
2826
+ INSERT INTO hats VALUES ('h8', 'black') RETURNING *;
2827
+ hat_name | hat_color
2828
+ ------------+------------
2829
+ h8 | black
2830
+ (1 row)
2831
+
2832
+ SELECT * FROM hat_data WHERE hat_name = 'h8';
2833
+ hat_name | hat_color
2834
+ ------------+------------
2835
+ h8 | black
2836
+ (1 row)
2837
+
2838
+ INSERT INTO hats VALUES ('h8', 'white') RETURNING *;
2839
+ hat_name | hat_color
2840
+ ------------+------------
2841
+ h8 | white
2842
+ (1 row)
2843
+
2844
+ SELECT * FROM hat_data WHERE hat_name = 'h8';
2845
+ hat_name | hat_color
2846
+ ------------+------------
2847
+ h8 | white
2848
+ (1 row)
2849
+
2850
+ INSERT INTO hats VALUES ('h8', 'forbidden') RETURNING *;
2851
+ hat_name | hat_color
2852
+ ----------+-----------
2853
+ (0 rows)
2854
+
2855
+ SELECT * FROM hat_data WHERE hat_name = 'h8';
2823
2856
hat_name | hat_color
2824
2857
------------+------------
2825
- h7 | Orange
2858
+ h8 | white
2826
2859
(1 row)
2827
2860
2828
2861
SELECT tablename, rulename, definition FROM pg_rules
2829
2862
WHERE tablename = 'hats';
2830
- tablename | rulename | definition
2831
- -----------+------------+-----------------------------------------------------------------------------------------------
2832
- hats | hat_upsert | CREATE RULE hat_upsert AS +
2833
- | | ON INSERT TO hats DO INSTEAD INSERT INTO hat_data (hat_name, hat_color) +
2834
- | | VALUES (new.hat_name, new.hat_color) ON CONFLICT DO UPDATE SET hat_color = 'Orange'::bpchar+
2835
- | | RETURNING hat_data.hat_name, +
2863
+ tablename | rulename | definition
2864
+ -----------+------------+-------------------------------------------------------------------------------------------------------------------------------
2865
+ hats | hat_upsert | CREATE RULE hat_upsert AS +
2866
+ | | ON INSERT TO hats DO INSTEAD INSERT INTO hat_data (hat_name, hat_color) +
2867
+ | | VALUES (new.hat_name, new.hat_color) ON CONFLICT DO UPDATE SET hat_name = hat_data.hat_name, hat_color = excluded.hat_color+
2868
+ | | WHERE (excluded.hat_color <> 'forbidden'::bpchar) +
2869
+ | | RETURNING hat_data.hat_name, +
2836
2870
| | hat_data.hat_color;
2837
2871
(1 row)
2838
2872
2873
+ -- ensure explain works for on insert conflict rules
2874
+ explain (costs off) INSERT INTO hats VALUES ('h8', 'forbidden') RETURNING *;
2875
+ QUERY PLAN
2876
+ ----------------------------------------------------------------
2877
+ Insert on hat_data
2878
+ Conflict Resolution: UPDATE
2879
+ Conflict Arbiter Indexes: hat_data_pkey
2880
+ Conflict Filter: (excluded.hat_color <> 'forbidden'::bpchar)
2881
+ -> Result
2882
+ (5 rows)
2883
+
2884
+ -- ensure upserting into a rule, with a CTE (different offsets!) works
2885
+ WITH data(hat_name, hat_color) AS (
2886
+ VALUES ('h8', 'green'),
2887
+ ('h9', 'blue'),
2888
+ ('h7', 'forbidden')
2889
+ )
2890
+ INSERT INTO hats
2891
+ SELECT * FROM data
2892
+ RETURNING *;
2893
+ hat_name | hat_color
2894
+ ------------+------------
2895
+ h8 | green
2896
+ h9 | blue
2897
+ (2 rows)
2898
+
2899
+ EXPLAIN (costs off) WITH data(hat_name, hat_color) AS (
2900
+ VALUES ('h8', 'green'),
2901
+ ('h9', 'blue'),
2902
+ ('h7', 'forbidden')
2903
+ )
2904
+ INSERT INTO hats
2905
+ SELECT * FROM data
2906
+ RETURNING *;
2907
+ QUERY PLAN
2908
+ ----------------------------------------------------------------
2909
+ Insert on hat_data
2910
+ Conflict Resolution: UPDATE
2911
+ Conflict Arbiter Indexes: hat_data_pkey
2912
+ Conflict Filter: (excluded.hat_color <> 'forbidden'::bpchar)
2913
+ CTE data
2914
+ -> Values Scan on "*VALUES*"
2915
+ -> CTE Scan on data
2916
+ (7 rows)
2917
+
2918
+ SELECT * FROM hat_data WHERE hat_name IN ('h8', 'h9', 'h7') ORDER BY hat_name;
2919
+ hat_name | hat_color
2920
+ ------------+------------
2921
+ h7 | black
2922
+ h8 | green
2923
+ h9 | blue
2924
+ (3 rows)
2925
+
2839
2926
DROP RULE hat_upsert ON hats;
2840
2927
drop table hats;
2841
2928
drop table hat_data;
0 commit comments