From c7d40ff35fe3f203d166e999da42e6e150859a36 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 13 Nov 2005 19:12:05 +0000 Subject: [PATCH] Force the second argument of SUBSTRING(foo FOR bar) to be int4, to avoid surprising results when it's some other numeric type. This doesn't solve the generic problem of surprising implicit casts to text, but it's a low-impact way of making sure this particular case behaves sanely. Per gripe from Harald Fuchs and subsequent discussion. --- src/backend/parser/gram.y | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 766fe912d55..43f74fc011e 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.481 2004/12/31 22:00:27 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.481.4.1 2005/11/13 19:12:05 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -7137,9 +7137,10 @@ position_list: * SQL9x defines a specific syntax for arguments to SUBSTRING(): * o substring(text from int for int) * o substring(text from int) get entire string from starting point "int" - * o substring(text from pattern) get entire string matching pattern * o substring(text for int) get first "int" characters of string - * We also want to implement generic substring functions which accept + * o substring(text from pattern) get entire string matching pattern + * o substring(text from pattern for escape) same with specified escape char + * We also want to support generic substring functions which accept * the usual generic list of arguments. So we will accept both styles * here, and convert the SQL9x style to the generic list for further * processing. - thomas 2000-11-28 @@ -7151,6 +7152,7 @@ substr_list: } | a_expr substr_for substr_from { + /* not legal per SQL99, but might as well allow it */ $$ = list_make3($1, $3, $2); } | a_expr substr_from @@ -7159,10 +7161,18 @@ substr_list: } | a_expr substr_for { + /* + * Since there are no cases where this syntax allows + * a textual FOR value, we forcibly cast the argument + * to int4. This is a kluge to avoid surprising results + * when the argument is, say, int8. It'd be better if + * there were not an implicit cast from int8 to text ... + */ A_Const *n = makeNode(A_Const); n->val.type = T_Integer; n->val.val.ival = 1; - $$ = list_make3($1, (Node *)n, $2); + $$ = list_make3($1, (Node *) n, + makeTypeCast($2, SystemTypeName("int4"))); } | expr_list { -- 2.39.5