Mysterious ::text::char cast: ascii(chr(32)::char) = 0

Started by Joel Jacobsonalmost 5 years ago2 messages
#1Joel Jacobson
joel@compiler.org

Hi,

In testing the regex engine, I found a strange case that puzzles me.

When a text string of a single space character is casted to a character,
I would assume the result to be, a space character,
but for some reason it's the null character.

Trying to produce a text with null character gives an error, like expected:

SELECT chr(0);
ERROR: null character not permitted

SELECT c = ascii(chr(c)::char), COUNT(*) FROM generate_series(1,255) AS c GROUP BY 1;
f | 1
t | 254

SELECT * FROM generate_series(1,255) AS c WHERE c <> ascii(chr(c)::char);
32

It's only character 32 that has this "special effect".

/Joel

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joel Jacobson (#1)
Re: Mysterious ::text::char cast: ascii(chr(32)::char) = 0

"Joel Jacobson" <joel@compiler.org> writes:

When a text string of a single space character is casted to a character,
I would assume the result to be, a space character,
but for some reason it's the null character.

This is because of the weird semantics of char(N). chr(32) produces
a TEXT value containing one space, which you then cast to CHAR(1),
making the trailing space semantically insignificant. But the
ascii() function requires a TEXT argument, so we immediately cast
the string back to TEXT, and that cast is defined to strip any
trailing spaces. Thus, what gets delivered to ascii() is an empty
TEXT string, causing it to return 0.

If you'd just done ascii(chr(c)), you'd have gotten c.

regards, tom lane