You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Fix ON CONFLICT DO NOTHING/UPDATE for temporal indexes
A PRIMARY KEY or UNIQUE constraint with WITHOUT OVERLAPS will be aGiST index, not a B-Tree, but it will still have indisunique set. Thecode for ON CONFLICT fails if it sees a non-btree index that hasindisunique. This commit fixes that and adds some tests. But nowthat we can't just test indisunique, we also need some extra checks toprevent DO UPDATE from running against a WITHOUT OVERLAPS constraint(because the conflict could happen against more than one row, and we'donly update one).Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>Discussion:https://www.postgresql.org/message-id/1426589a-83cb-4a89-bf40-713970c07e63@illuminatedcomputing.com
Copy file name to clipboardExpand all lines: src/test/regress/expected/without_overlaps.out
+176Lines changed: 176 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -453,6 +453,182 @@ DROP TABLE temporal_partitioned;
453
453
ALTER TABLE temporal_rng REPLICA IDENTITY USING INDEX temporal_rng_pk;
454
454
ERROR: cannot use non-unique index "temporal_rng_pk" as replica identity
455
455
--
456
+
-- ON CONFLICT
457
+
--
458
+
TRUNCATE temporal_rng;
459
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
460
+
-- with a conflict
461
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING;
462
+
-- id matches but no conflict
463
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING;
464
+
-- date matches but no conflict
465
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING;
466
+
SELECT * FROM temporal_rng ORDER BY id, valid_at;
467
+
id | valid_at
468
+
-------+-------------------------
469
+
[1,2) | [2000-01-01,2010-01-01)
470
+
[1,2) | [2010-01-01,2020-01-01)
471
+
[2,3) | [2005-01-01,2006-01-01)
472
+
(3 rows)
473
+
474
+
TRUNCATE temporal_rng;
475
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
476
+
-- with a conflict
477
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING;
478
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
479
+
-- id matches but no conflict
480
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING;
481
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
482
+
-- date matches but no conflict
483
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING;
484
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
485
+
SELECT * FROM temporal_rng ORDER BY id, valid_at;
486
+
id | valid_at
487
+
-------+-------------------------
488
+
[1,2) | [2000-01-01,2010-01-01)
489
+
(1 row)
490
+
491
+
TRUNCATE temporal_rng;
492
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
493
+
-- with a conflict
494
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING;
495
+
-- id matches but no conflict
496
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING;
497
+
-- date matches but no conflict
498
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING;
499
+
SELECT * FROM temporal_rng ORDER BY id, valid_at;
500
+
id | valid_at
501
+
-------+-------------------------
502
+
[1,2) | [2000-01-01,2010-01-01)
503
+
[1,2) | [2010-01-01,2020-01-01)
504
+
[2,3) | [2005-01-01,2006-01-01)
505
+
(3 rows)
506
+
507
+
TRUNCATE temporal_rng;
508
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
509
+
-- with a conflict
510
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)';
511
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
512
+
-- id matches but no conflict
513
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)';
514
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
515
+
-- date matches but no conflict
516
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)';
517
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
518
+
SELECT * FROM temporal_rng ORDER BY id, valid_at;
519
+
id | valid_at
520
+
-------+-------------------------
521
+
[1,2) | [2000-01-01,2010-01-01)
522
+
(1 row)
523
+
524
+
TRUNCATE temporal_rng;
525
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
526
+
-- with a conflict
527
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[2,3)';
528
+
ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints
529
+
-- id matches but no conflict
530
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[3,4)';
531
+
ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints
532
+
-- date matches but no conflict
533
+
INSERT INTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal_rng_pk DO UPDATE SET id = EXCLUDED.id + '[4,5)';
534
+
ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints
535
+
SELECT * FROM temporal_rng ORDER BY id, valid_at;
536
+
id | valid_at
537
+
-------+-------------------------
538
+
[1,2) | [2000-01-01,2010-01-01)
539
+
(1 row)
540
+
541
+
-- with a UNIQUE constraint:
542
+
CREATE TABLE temporal3 (
543
+
id int4range,
544
+
valid_at daterange,
545
+
CONSTRAINT temporal3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
546
+
);
547
+
TRUNCATE temporal3;
548
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
549
+
-- with a conflict
550
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING;
551
+
-- id matches but no conflict
552
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING;
553
+
-- date matches but no conflict
554
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING;
555
+
SELECT * FROM temporal3 ORDER BY id, valid_at;
556
+
id | valid_at
557
+
-------+-------------------------
558
+
[1,2) | [2000-01-01,2010-01-01)
559
+
[1,2) | [2010-01-01,2020-01-01)
560
+
[2,3) | [2005-01-01,2006-01-01)
561
+
(3 rows)
562
+
563
+
TRUNCATE temporal3;
564
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
565
+
-- with a conflict
566
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING;
567
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
568
+
-- id matches but no conflict
569
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING;
570
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
571
+
-- date matches but no conflict
572
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING;
573
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
574
+
SELECT * FROM temporal3 ORDER BY id, valid_at;
575
+
id | valid_at
576
+
-------+-------------------------
577
+
[1,2) | [2000-01-01,2010-01-01)
578
+
(1 row)
579
+
580
+
TRUNCATE temporal3;
581
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
582
+
-- with a conflict
583
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING;
584
+
-- id matches but no conflict
585
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING;
586
+
-- date matches but no conflict
587
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO NOTHING;
588
+
SELECT * FROM temporal3 ORDER BY id, valid_at;
589
+
id | valid_at
590
+
-------+-------------------------
591
+
[1,2) | [2000-01-01,2010-01-01)
592
+
[1,2) | [2010-01-01,2020-01-01)
593
+
[2,3) | [2005-01-01,2006-01-01)
594
+
(3 rows)
595
+
596
+
TRUNCATE temporal3;
597
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
598
+
-- with a conflict
599
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[2,3)';
600
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
601
+
-- id matches but no conflict
602
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[3,4)';
603
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
604
+
-- date matches but no conflict
605
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATE SET id = EXCLUDED.id + '[4,5)';
606
+
ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
607
+
SELECT * FROM temporal3 ORDER BY id, valid_at;
608
+
id | valid_at
609
+
-------+-------------------------
610
+
[1,2) | [2000-01-01,2010-01-01)
611
+
(1 row)
612
+
613
+
TRUNCATE temporal3;
614
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01'));
615
+
-- with a conflict
616
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[2,3)';
617
+
ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints
618
+
-- id matches but no conflict
619
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[3,4)';
620
+
ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints
621
+
-- date matches but no conflict
622
+
INSERT INTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ON CONSTRAINT temporal3_uq DO UPDATE SET id = EXCLUDED.id + '[4,5)';
623
+
ERROR: ON CONFLICT DO UPDATE not supported with exclusion constraints
624
+
SELECT * FROM temporal3 ORDER BY id, valid_at;
625
+
id | valid_at
626
+
-------+-------------------------
627
+
[1,2) | [2000-01-01,2010-01-01)
628
+
(1 row)
629
+
630
+
DROP TABLE temporal3;
631
+
--
456
632
-- test FK dependencies
457
633
--
458
634
-- can't drop a range referenced by an FK, unless with CASCADE