Crea un UNIQUE índice de varias columnas en (product_id, variant_id) :
CREATE UNIQUE INDEX line_items_prod_var_idx ON line_items (product_id, variant_id);
Sin embargo, esto permitiría múltiples entradas de (1, NULL) para (product_id, variant_id) porque NULL los valores no se consideran idénticos.
Para compensar eso, cree adicionalmente un UNIQUE parcial índice en product_id :
CREATE UNIQUE INDEX line_items_prod_var_null_idx ON line_items (product_id)
WHERE variant_id IS NULL;
De esta manera puede ingresar (1,2) , (1,3) y (1, NULL) , pero ninguno de ellos por segunda vez. También acelera las consultas con condiciones en una o ambas columnas.
Respuesta reciente relacionada en dba.SE, casi directamente aplicable a su caso:
- Restricción única de varias columnas de PostgreSQL y valores NULL