Received: from maia.hub.org (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id 670E2633D47 for ; Wed, 13 Jan 2010 11:35:48 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 79257-04 for ; Wed, 13 Jan 2010 15:35:37 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from sss.pgh.pa.us (sss.pgh.pa.us [66.207.139.130]) by mail.postgresql.org (Postfix) with ESMTP id E2B23633D75 for ; Wed, 13 Jan 2010 11:35:37 -0400 (AST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss.pgh.pa.us (8.14.2/8.14.2) with ESMTP id o0DFZZgx010879; Wed, 13 Jan 2010 10:35:35 -0500 (EST) To: "Charles O'Farrell" cc: pgsql-bugs@postgresql.org Subject: Re: Substring auto trim In-reply-to: <65d71e1c1001130102j5f46299cm87477efcfd0c5a51@mail.gmail.com> References: <65d71e1c1001130102j5f46299cm87477efcfd0c5a51@mail.gmail.com> Comments: In-reply-to "Charles O'Farrell" message dated "Wed, 13 Jan 2010 19:02:31 +1000" Date: Wed, 13 Jan 2010 10:35:35 -0500 Message-ID: <10878.1263396935@sss.pgh.pa.us> From: Tom Lane X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0.589 tagged_above=-10 required=5 tests=BAYES_00=-2.599, FH_DATE_PAST_20XX=3.188 X-Spam-Level: X-Archive-Number: 201001/111 X-Sequence-Number: 25615 "Charles O'Farrell" writes: > We have a column 'foo' which is of type character (not varying). > select substr(foo, 1, 10) from bar > The result of this query are values whose trailing spaces have been trimmed > automatically. This causes incorrect results when comparing to a value that > may contain trailing spaces. What's the data type of the value being compared to? I get, for instance, postgres=# select substr('ab '::char(4), 1, 4) = 'ab '::char(4); ?column? ---------- t (1 row) The actual value coming out of the substr() is indeed just 'ab', but that ought to be considered equal to 'ab ' anyway in char(n) semantics. Postgres considers that trailing blanks in a char(n) value are semantically insignificant, so it strips them when converting to a type where they would be significant (ie, text or varchar). What's happening in this scenario is that substr() is defined to take and return text, so the stripping happens before substr ever sees it. As Pavel noted, you could possibly work around this particular case by defining a variant of substr() that takes and returns char(n), but on the whole I'd strongly advise switching over to varchar/text if possible. The semantics of char(n) are so weird/braindamaged that it's best avoided. BTW, if you do want to use the workaround, this seems sufficient: create function substr(char,int,int) returns char strict immutable language internal as 'text_substr' ; It's the same C code, you're just avoiding the coercion on input. regards, tom lane