Search code examples
postgresqlcheck-constraints

check constraint being printed without parenthesis


I have this DDL:

CREATE TABLE checkout_value (
    id BIGSERIAL PRIMARY KEY,
    start_value INTEGER,
    end_value INTEGER,
);

With an e-commerce in mind, I want to save several ranges of possible values, where future rules will be applied at checkout. examples:

  1. values until $20
  2. values from $400
  3. between $30 and $300

This way, I want to allow one null value, but if both are not null, start_value should be smaller than end_value.

I though about triggers, but I'm trying to do this using a check constraint, this way:

CREATE TABLE checkout_value (
    id BIGSERIAL PRIMARY KEY,
    start_value INTEGER,
    end_value INTEGER,
    CHECK 
    (
        (start_value IS NOT NULL AND end_value IS NULL)
        OR
        (start_value IS NULL AND end_value IS NOT NULL)
        OR
        (start_value IS NOT NULL AND end_value IS NOT NULL AND end_value > start_value)
    )
);

this works! but when I run \d checkout_value, it prints without any parenthesis:

Check constraints:
  "checkout_value_check" CHECK (start_value IS NOT NULL AND end_value IS NULL OR start_value IS NULL AND end_value IS NOT NULL OR start_value IS NOT NULL AND end_value IS NOT NULL AND end_value > start_value)

which, without parenthesis, would lead to an unwanted rule. Is this a bug at printing the details of the table? Is there an easier way to apply while documenting these rules in a more explicit way?


Solution

  • AND binds stronger than OR, so both versions are equivalent. PostgreSQL doesn't store the string, but the parsed expression.