reference: https://www.postgresql.org/docs/current/catalog-pg-operator.html
SELECT
oprname,
p1.typname AS left_type,
p2.typname AS right_type,
p3.typname AS result_type,
oprcode
FROM
pg_operator po
JOIN pg_type p1 ON p1.oid = po.oprleft
JOIN pg_type p2 ON p2.oid = po.oprright
JOIN pg_type p3 ON p3.oid = po.oprresult
WHERE
oprname = '+'
AND p1.typname = 'date'::name;
So there is a row like :
oprname | left_type | right_type | result_type | oprcode
---------+-----------+------------+-------------+------------------
+ | date | int4 | date | date_pli
That's why select now()::date + 1;
will work.
But is there a way to add days/months/years to a date without the
result being time stamp and also obviously without casting? Or is
casting the only way?
"add days/months/years" Means:
Is there a operator that right side (or left side) is interval data type then the return is date data type.
Does it exist? we can query the catalog schema and find out.
SELECT
oprname,
p1.typname AS left_type, --left side of a operator data type
p2.typname AS right_type, --right side of a operator data type
p3.typname AS result_type, --return data type
oprcode
FROM
pg_operator po
JOIN pg_type p1 ON p1.oid = po.oprleft
JOIN pg_type p2 ON p2.oid = po.oprright
JOIN pg_type p3 ON p3.oid = po.oprresult
WHERE
p1.typname = 'interval'::name
OR p2.typname = 'interval'::name;
oprname | left_type | right_type | result_type | oprcode
---------+-------------+-------------+-------------+-------------------------
+ | date | interval | timestamp | date_pl_interval
- | date | interval | timestamp | date_mi_interval
+ | timestamptz | interval | timestamptz | timestamptz_pl_interval
- | timestamptz | interval | timestamptz | timestamptz_mi_interval
= | interval | interval | bool | interval_eq
<> | interval | interval | bool | interval_ne
< | interval | interval | bool | interval_lt
<= | interval | interval | bool | interval_le
> | interval | interval | bool | interval_gt
>= | interval | interval | bool | interval_ge
+ | interval | interval | interval | interval_pl
- | interval | interval | interval | interval_mi
* | interval | float8 | interval | interval_mul
* | float8 | interval | interval | mul_d_interval
/ | interval | float8 | interval | interval_div
+ | time | interval | time | time_pl_interval
- | time | interval | time | time_mi_interval
+ | timetz | interval | timetz | timetz_pl_interval
- | timetz | interval | timetz | timetz_mi_interval
+ | interval | time | time | interval_pl_time
+ | timestamp | interval | timestamp | timestamp_pl_interval
- | timestamp | interval | timestamp | timestamp_mi_interval
+ | interval | date | timestamp | interval_pl_date
+ | interval | timetz | timetz | interval_pl_timetz
+ | interval | timestamp | timestamp | interval_pl_timestamp
+ | interval | timestamptz | timestamptz | interval_pl_timestamptz
<-> | interval | interval | interval | interval_dist
(27 rows)
As you can see the query column return type is {timestamp,timestamptz, bool, interval,time,timetz}. So it cannot return date.