Uff, to je nakládačka. :-)
MŠ: rozdíl mezi "primary key" a "index unique" je v tom, že pokud máš nenulový počet uživatelů, co mají nutkavou potřebu do tabulek lézt nějakým tim table view čumítkem a tyto klikátka chtějí zkrátka primární klíč na tabulce. Bez něj buď odmítnou zobrazit nebo se podivně pošahají, když v tabulce je 500M+ řádků. To je jediný důvod, proč byla snaha přidat primární klíč. Aplikačně to celé rychle žije z indexu, který si vyrábí na pozadí ta omezující podmínka na nevkládání překrývajících se dat.
Nu, stejná skupina má občas snahu psát dotazy, kde do where nacpou něco jako "lower(casr) between T1 and T2", tak jsem chtěl zabít dvě mouchy jedním klíčem, že by jim to trochu zrychlilo, když nejsou schopni pochopit range operaci typu casr && (T1, T2]. :-)
Ono při větším počtu řádků už ty indexy začínají i něco žrát času i místa na disku, tak jsem nechtěl kvůli tomu čumítku přidat tupě jen bigserial nebo něco takového.
Samozřejmě to jde řešit, že místo casr:tstzrange použít na to 3 samostatné sloupce (casl:timestamp, casu:timestamp, casb:char(2)) a vyrobit si nad tím primary index pomocí (smid, casl, casb) a kontrola nepřekrývání pomocí "exclude using gist (smid with =, tstzrange(casl, casu, casb) with &&)" funguje, akorát pak některé operace to nechtělo brát dle toho indexu na pozadí. Dotaz typu "select * from tab where tstzrange(casl, casu, casb) && '[ T1, T2]'" nechtěl použít index toho exclude, což při použití normálního range sloupce fungovalo. A historicky je to děláno vše na range, tak jsem nechtěl do toho tak hluboce rejpat.