The singleton range constructors don't work terribly well.
regression=# select int4range(42); -- okint4range
-----------[42,43)
(1 row)
regression=# select int4range(null); -- not so okint4range
-----------
(1 row)
regression=# select int4range('42'); -- clearly not ok
ERROR: malformed range literal: "42"
LINE 1: select int4range('42'); ^
DETAIL: Missing left parenthesis or bracket.
The second of these might at first glance seem all right; until you
remember that range_constructor1 is not strict and throws an error
on null input. So it's not getting called.
What is actually happening in both cases 2 and 3 is that
func_get_detail() is interpreting the syntax as equivalent to
'literal'::int4range. We do not have a whole lot of room to maneuver
here, because that equivalence is of very long standing; and as
mentioned in the comments in that function, we can't easily alter its
priority relative to other interpretations.
I don't immediately see a solution that's better than dropping the
single-argument range constructors. Even if you don't care that much
about the NULL case, things like this are pretty fatal from a usability
standpoint:
regression=# select daterange('2011-11-18');
ERROR: malformed range literal: "2011-11-18"
LINE 1: select daterange('2011-11-18'); ^
DETAIL: Missing left parenthesis or bracket.
I'm not sure that singleton ranges are so useful that we need to come up
with a short-form input method for them. (Yeah, I know that this case
could be fixed with an explicit cast, but if we leave it like this we'll
get a constant stream of bug reports about it.)
For that matter, the zero-argument range constructors seem like
mostly a waste of catalog space too ... what's wrong with writing
'empty'::int4range when you need that?
regards, tom lane