Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c857298

Browse files
committed
Allow I/O conversion casts to be applied to or from any type that is a member
of the STRING type category, thereby opening up the mechanism for user-defined types. This is mainly for the benefit of citext, though; there aren't likely to be a lot of types that are all general-purpose character strings. Per discussion with David Wheeler.
1 parent 7df49ce commit c857298

File tree

4 files changed

+43
-32
lines changed

4 files changed

+43
-32
lines changed

contrib/citext/expected/citext.out

+13-10
Original file line numberDiff line numberDiff line change
@@ -1141,13 +1141,16 @@ SELECT like_escape( name::text, ''::citext ) =like_escape( name::text, '' ) AS t
11411141
t
11421142
(5 rows)
11431143

1144-
--- TODO: Get citext working with magic cast functions?
1145-
SELECT cidr( '192.168.1.2'::citext ) = cidr( '192.168.1.2'::text ) AS "t TODO";
1146-
ERROR: function cidr(citext) does not exist
1147-
LINE 1: SELECT cidr( '192.168.1.2'::citext ) = cidr( '192.168.1.2'::...
1148-
^
1149-
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
1150-
SELECT '192.168.1.2'::cidr::citext = '192.168.1.2'::cidr::text AS "t TODO";
1151-
ERROR: cannot cast type cidr to citext
1152-
LINE 1: SELECT '192.168.1.2'::cidr::citext = '192.168.1.2'::cidr::te...
1153-
^
1144+
--- citext should work as source or destination of I/O conversion casts
1145+
SELECT cidr( '192.168.1.2'::citext ) = cidr( '192.168.1.2'::text ) AS "t";
1146+
t
1147+
---
1148+
t
1149+
(1 row)
1150+
1151+
SELECT '192.168.1.2'::cidr::citext = '192.168.1.2'::cidr::text AS "t";
1152+
t
1153+
---
1154+
t
1155+
(1 row)
1156+

contrib/citext/sql/citext.sql

+3-3
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,6 @@ SELECT COUNT(*) = 19::bigint AS t FROM try;
323323
SELECT like_escape( name, '' ) = like_escape( name::text, '' ) AS t FROM srt;
324324
SELECT like_escape( name::text, ''::citext ) =like_escape( name::text, '' ) AS t FROM srt;
325325

326-
--- TODO: Get citext working with magic cast functions?
327-
SELECT cidr( '192.168.1.2'::citext ) = cidr( '192.168.1.2'::text ) AS "t TODO";
328-
SELECT '192.168.1.2'::cidr::citext = '192.168.1.2'::cidr::text AS "t TODO";
326+
--- citext should work as source or destination of I/O conversion casts
327+
SELECT cidr( '192.168.1.2'::citext ) = cidr( '192.168.1.2'::text ) AS "t";
328+
SELECT '192.168.1.2'::cidr::citext = '192.168.1.2'::cidr::text AS "t";

doc/src/sgml/ref/create_cast.sgml

+22-10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.28 2008/07/12 16:20:06 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.29 2008/07/30 21:23:17 tgl Exp $ -->
22

33
<refentry id="SQL-CREATECAST">
44
<refmeta>
@@ -26,7 +26,7 @@ CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</r
2626
[ AS ASSIGNMENT | AS IMPLICIT ]
2727
</synopsis>
2828
</refsynopsisdiv>
29-
29+
3030
<refsect1 id="sql-createcast-description">
3131
<title>Description</title>
3232

@@ -131,6 +131,18 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
131131
to <type>int4</>, are best made explicit-only.
132132
</para>
133133

134+
<note>
135+
<para>
136+
Sometimes it is necessary for usability or standards-compliance reasons
137+
to provide multiple implicit casts among a set of types, resulting in
138+
ambiguity that cannot be avoided as above. The parser has a fallback
139+
heuristic based on <firstterm>type categories</> and <firstterm>preferred
140+
types</> that can help to provide desired behavior in such cases. See
141+
<xref linkend="sql-createtype" endterm="sql-createtype-title"> for
142+
more information.
143+
</para>
144+
</note>
145+
134146
<para>
135147
To be able to create a cast, you must own the source or the target
136148
data type. To create a binary-coercible cast, you must be superuser.
@@ -181,8 +193,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
181193

182194
<listitem>
183195
<para>
184-
Indicates that the source type and the target type are binary
185-
coercible, so no function is required to perform the cast.
196+
Indicates that the source type is binary-coercible to the target type,
197+
so no function is required to perform the cast.
186198
</para>
187199
</listitem>
188200
</varlistentry>
@@ -218,7 +230,7 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
218230
if there is none. The third argument,
219231
if present, must be type <type>boolean</>; it receives <literal>true</>
220232
if the cast is an explicit cast, <literal>false</> otherwise.
221-
(Bizarrely, the SQL spec demands different behaviors for explicit and
233+
(Bizarrely, the SQL standard demands different behaviors for explicit and
222234
implicit casts in some cases. This argument is supplied for functions
223235
that must implement such casts. It is not recommended that you design
224236
your own data types so that this matters.)
@@ -271,7 +283,8 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
271283
<para>
272284
It is normally not necessary to create casts between user-defined types
273285
and the standard string types (<type>text</>, <type>varchar</>, and
274-
<type>char(<replaceable>n</>)</type>). <productname>PostgreSQL</> will
286+
<type>char(<replaceable>n</>)</type>, as well as user-defined types that
287+
are defined to be in the string category). <productname>PostgreSQL</> will
275288
automatically handle a cast to a string type by invoking the other
276289
type's output function, or conversely handle a cast from a string type
277290
by invoking the other type's input function. These
@@ -340,16 +353,15 @@ SELECT CAST ( 2 AS numeric ) + 4.0;
340353
<title>Examples</title>
341354

342355
<para>
343-
To create a cast from type <type>bigint</type> to type
356+
To create an assignment cast from type <type>bigint</type> to type
344357
<type>int4</type> using the function <literal>int4(bigint)</literal>:
345358
<programlisting>
346-
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint);
359+
CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;
347360
</programlisting>
348361
(This cast is already predefined in the system.)
349362
</para>
350363
</refsect1>
351364

352-
353365
<refsect1 id="sql-createcast-compat">
354366
<title>Compatibility</title>
355367

@@ -358,7 +370,7 @@ CREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint);
358370
<acronym>SQL</acronym> standard,
359371
except that SQL does not make provisions for binary-coercible
360372
types or extra arguments to implementation functions.
361-
<literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname>
373+
<literal>AS IMPLICIT</> is a <productname>PostgreSQL</productname>
362374
extension, too.
363375
</para>
364376
</refsect1>

src/backend/parser/parse_coerce.c

+5-9
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.162 2008/07/30 17:05:04 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.163 2008/07/30 21:23:17 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1796,8 +1796,8 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
17961796

17971797
/*
17981798
* If we still haven't found a possibility, consider automatic casting
1799-
* using I/O functions. We allow assignment casts to textual types
1800-
* and explicit casts from textual types to be handled this way. (The
1799+
* using I/O functions. We allow assignment casts to string types
1800+
* and explicit casts from string types to be handled this way. (The
18011801
* CoerceViaIO mechanism is a lot more general than that, but this is
18021802
* all we want to allow in the absence of a pg_cast entry.) It would
18031803
* probably be better to insist on explicit casts in both directions,
@@ -1807,14 +1807,10 @@ find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId,
18071807
if (result == COERCION_PATH_NONE)
18081808
{
18091809
if (ccontext >= COERCION_ASSIGNMENT &&
1810-
(targetTypeId == TEXTOID ||
1811-
targetTypeId == VARCHAROID ||
1812-
targetTypeId == BPCHAROID))
1810+
TypeCategory(targetTypeId) == TYPCATEGORY_STRING)
18131811
result = COERCION_PATH_COERCEVIAIO;
18141812
else if (ccontext >= COERCION_EXPLICIT &&
1815-
(sourceTypeId == TEXTOID ||
1816-
sourceTypeId == VARCHAROID ||
1817-
sourceTypeId == BPCHAROID))
1813+
TypeCategory(sourceTypeId) == TYPCATEGORY_STRING)
18181814
result = COERCION_PATH_COERCEVIAIO;
18191815
}
18201816
}

0 commit comments

Comments
 (0)