Skip to content

Commit f245c4e

Browse files
committed
When implementing a coercion to a domain type with a combined
type-and-length coercion function, make sure that the coercion function is told the correct typmod. Fixes Kris Jurka's example of a domain over bit(N).
1 parent a981b02 commit f245c4e

File tree

5 files changed

+40
-22
lines changed

5 files changed

+40
-22
lines changed

src/backend/commands/copy.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.233 2004/10/29 19:18:22 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.234 2004/11/06 17:46:27 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1596,7 +1596,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
15961596
node = coerce_to_domain((Node *) prm,
15971597
prm->paramtype,
15981598
attr[attnum - 1]->atttypid,
1599-
COERCE_IMPLICIT_CAST, false);
1599+
COERCE_IMPLICIT_CAST, false, false);
16001600

16011601
constraintexprs[attnum - 1] = ExecPrepareExpr((Expr *) node,
16021602
estate);

src/backend/optimizer/prep/preptlist.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1994, Regents of the University of California
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.70 2004/08/29 04:12:34 momjian Exp $
18+
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.71 2004/11/06 17:46:30 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -200,6 +200,7 @@ expand_targetlist(List *tlist, int command_type,
200200
InvalidOid,
201201
atttype,
202202
COERCE_IMPLICIT_CAST,
203+
false,
203204
false);
204205
}
205206
else

src/backend/parser/parse_coerce.c

Lines changed: 31 additions & 16 deletions
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.123 2004/08/29 05:06:44 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.124 2004/11/06 17:46:33 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -191,7 +191,7 @@ coerce_type(ParseState *pstate, Node *node,
191191
/* If target is a domain, apply constraints. */
192192
if (targetTyptype == 'd')
193193
result = coerce_to_domain(result, InvalidOid, targetTypeId,
194-
cformat, false);
194+
cformat, false, false);
195195

196196
ReleaseSysCache(targetType);
197197

@@ -253,23 +253,33 @@ coerce_type(ParseState *pstate, Node *node,
253253
* Generate an expression tree representing run-time
254254
* application of the conversion function. If we are dealing
255255
* with a domain target type, the conversion function will
256-
* yield the base type (and we assume targetTypeMod must be
257-
* -1).
256+
* yield the base type, and we need to extract the correct
257+
* typmod to use from the domain's typtypmod.
258258
*/
259259
Oid baseTypeId = getBaseType(targetTypeId);
260+
int32 baseTypeMod;
261+
262+
if (targetTypeId != baseTypeId)
263+
baseTypeMod = get_typtypmod(targetTypeId);
264+
else
265+
baseTypeMod = targetTypeMod;
260266

261267
result = build_coercion_expression(node, funcId,
262-
baseTypeId, targetTypeMod,
268+
baseTypeId, baseTypeMod,
263269
cformat,
264270
(cformat != COERCE_IMPLICIT_CAST));
265271

266272
/*
267273
* If domain, coerce to the domain type and relabel with
268-
* domain type ID
274+
* domain type ID. We can skip the internal length-coercion
275+
* step if the selected coercion function was a type-and-length
276+
* coercion.
269277
*/
270278
if (targetTypeId != baseTypeId)
271279
result = coerce_to_domain(result, baseTypeId, targetTypeId,
272-
cformat, true);
280+
cformat, true,
281+
exprIsLengthCoercion(result,
282+
NULL));
273283
}
274284
else
275285
{
@@ -284,7 +294,7 @@ coerce_type(ParseState *pstate, Node *node,
284294
* then we won't need a RelabelType node.
285295
*/
286296
result = coerce_to_domain(node, InvalidOid, targetTypeId,
287-
cformat, false);
297+
cformat, false, false);
288298
if (result == node)
289299
{
290300
/*
@@ -425,15 +435,16 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *target_typeids,
425435
* 'typeId': target type to coerce to
426436
* 'cformat': coercion format
427437
* 'hideInputCoercion': if true, hide the input coercion under this one.
438+
* 'lengthCoercionDone': if true, caller already accounted for length.
428439
*
429440
* If the target type isn't a domain, the given 'arg' is returned as-is.
430441
*/
431442
Node *
432443
coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
433-
CoercionForm cformat, bool hideInputCoercion)
444+
CoercionForm cformat, bool hideInputCoercion,
445+
bool lengthCoercionDone)
434446
{
435447
CoerceToDomain *result;
436-
int32 typmod;
437448

438449
/* Get the base type if it hasn't been supplied */
439450
if (baseTypeId == InvalidOid)
@@ -461,12 +472,16 @@ coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
461472
* that would be safe to do anyway, without lots of knowledge about
462473
* what the base type thinks the typmod means.
463474
*/
464-
typmod = get_typtypmod(typeId);
465-
if (typmod >= 0)
466-
arg = coerce_type_typmod(arg, baseTypeId, typmod,
467-
COERCE_IMPLICIT_CAST,
468-
(cformat != COERCE_IMPLICIT_CAST),
469-
false);
475+
if (!lengthCoercionDone)
476+
{
477+
int32 typmod = get_typtypmod(typeId);
478+
479+
if (typmod >= 0)
480+
arg = coerce_type_typmod(arg, baseTypeId, typmod,
481+
COERCE_IMPLICIT_CAST,
482+
(cformat != COERCE_IMPLICIT_CAST),
483+
false);
484+
}
470485

471486
/*
472487
* Now build the domain coercion node. This represents run-time

src/backend/rewrite/rewriteHandler.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.144 2004/08/29 05:06:47 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.145 2004/11/06 17:46:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -374,6 +374,7 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
374374
InvalidOid,
375375
att_tup->atttypid,
376376
COERCE_IMPLICIT_CAST,
377+
false,
377378
false);
378379
}
379380
}

src/include/parser/parse_coerce.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.58 2004/08/29 04:13:09 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/parser/parse_coerce.h,v 1.59 2004/11/06 17:46:38 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -50,7 +50,8 @@ extern Node *coerce_type(ParseState *pstate, Node *node,
5050
Oid inputTypeId, Oid targetTypeId, int32 targetTypeMod,
5151
CoercionContext ccontext, CoercionForm cformat);
5252
extern Node *coerce_to_domain(Node *arg, Oid baseTypeId, Oid typeId,
53-
CoercionForm cformat, bool hideInputCoercion);
53+
CoercionForm cformat, bool hideInputCoercion,
54+
bool lengthCoercionDone);
5455

5556
extern Node *coerce_to_boolean(ParseState *pstate, Node *node,
5657
const char *constructName);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy