Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7173c48

Browse files
committed
Fix exprTypmod to recognize length-coercion function expressions,
such as bpchar(char_expression, N), and pull out the attrtypmod thatthe function is coercing to. This allows correct deduction of thecolumn type in examples such asCREATE VIEW v AS SELECT f1::char(8) FROM tbl;Formerly we labeled v's column as char-of-unknown-length not char(8).Also, this change causes the parser not to insert a redundant lengthcoercion function if the user has explicitly casted an INSERT or UPDATEexpression to the right length.
1 parentcbf4c96 commit7173c48

File tree

2 files changed

+105
-2
lines changed

2 files changed

+105
-2
lines changed

‎src/backend/parser/parse_expr.c

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.70 2000/02/21 18:47:02 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.71 2000/02/26 21:11:10 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515

1616
#include"postgres.h"
1717

1818
#include"catalog/pg_operator.h"
19+
#include"catalog/pg_proc.h"
1920
#include"nodes/makefuncs.h"
2021
#include"nodes/params.h"
2122
#include"nodes/relation.h"
@@ -29,6 +30,7 @@
2930
#include"parser/parse_relation.h"
3031
#include"parser/parse_target.h"
3132
#include"utils/builtins.h"
33+
#include"utils/syscache.h"
3234

3335
staticNode*parser_typecast_constant(Value*expr,TypeName*typename);
3436
staticNode*parser_typecast_expression(ParseState*pstate,
@@ -701,6 +703,15 @@ exprTypmod(Node *expr)
701703
}
702704
}
703705
break;
706+
caseT_Expr:
707+
{
708+
int32coercedTypmod;
709+
710+
/* Be smart about length-coercion functions... */
711+
if (exprIsLengthCoercion(expr,&coercedTypmod))
712+
returncoercedTypmod;
713+
}
714+
break;
704715
caseT_RelabelType:
705716
return ((RelabelType*)expr)->resulttypmod;
706717
break;
@@ -710,6 +721,97 @@ exprTypmod(Node *expr)
710721
return-1;
711722
}
712723

724+
/*
725+
* exprIsLengthCoercion
726+
*Detect whether an expression tree is an application of a datatype's
727+
*typmod-coercion function. Optionally extract the result's typmod.
728+
*
729+
* If coercedTypmod is not NULL, the typmod is stored there if the expression
730+
* is a length-coercion function, else -1 is stored there.
731+
*
732+
* We assume that a two-argument function named for a datatype, whose
733+
* output and first argument types are that datatype, and whose second
734+
* input is an int32 constant, represents a forced length coercion.
735+
* XXX It'd be better if the parsetree retained some explicit indication
736+
* of the coercion, so we didn't need these heuristics.
737+
*/
738+
bool
739+
exprIsLengthCoercion(Node*expr,int32*coercedTypmod)
740+
{
741+
Func*func;
742+
Const*second_arg;
743+
HeapTupletup;
744+
Form_pg_procprocStruct;
745+
Form_pg_typetypeStruct;
746+
747+
if (coercedTypmod!=NULL)
748+
*coercedTypmod=-1;/* default result on failure */
749+
750+
/* Is it a function-call at all? */
751+
if (expr==NULL||
752+
!IsA(expr,Expr)||
753+
((Expr*)expr)->opType!=FUNC_EXPR)
754+
return false;
755+
func= (Func*) (((Expr*)expr)->oper);
756+
Assert(IsA(func,Func));
757+
758+
/*
759+
* If it's not a two-argument function with the second argument being
760+
* an int4 constant, it can't have been created from a length coercion.
761+
*/
762+
if (length(((Expr*)expr)->args)!=2)
763+
return false;
764+
second_arg= (Const*)lsecond(((Expr*)expr)->args);
765+
if (!IsA(second_arg,Const)||
766+
second_arg->consttype!=INT4OID||
767+
second_arg->constisnull)
768+
return false;
769+
770+
/*
771+
* Lookup the function in pg_proc
772+
*/
773+
tup=SearchSysCacheTuple(PROCOID,
774+
ObjectIdGetDatum(func->funcid),
775+
0,0,0);
776+
if (!HeapTupleIsValid(tup))
777+
elog(ERROR,"cache lookup for proc %u failed",func->funcid);
778+
procStruct= (Form_pg_proc)GETSTRUCT(tup);
779+
780+
/*
781+
* It must be a function with two arguments where the first is of
782+
* the same type as the return value and the second is an int4.
783+
* Also, just to be sure, check return type agrees with expr node.
784+
*/
785+
if (procStruct->pronargs!=2||
786+
procStruct->prorettype!=procStruct->proargtypes[0]||
787+
procStruct->proargtypes[1]!=INT4OID||
788+
procStruct->prorettype!= ((Expr*)expr)->typeOid)
789+
return false;
790+
791+
/*
792+
* Furthermore, the name of the function must be the same
793+
* as the argument/result type's name.
794+
*/
795+
tup=SearchSysCacheTuple(TYPEOID,
796+
ObjectIdGetDatum(procStruct->prorettype),
797+
0,0,0);
798+
if (!HeapTupleIsValid(tup))
799+
elog(ERROR,"cache lookup for type %u failed",
800+
procStruct->prorettype);
801+
typeStruct= (Form_pg_type)GETSTRUCT(tup);
802+
if (strncmp(NameStr(procStruct->proname),
803+
NameStr(typeStruct->typname),
804+
NAMEDATALEN)!=0)
805+
return false;
806+
807+
/*
808+
* OK, it is indeed a length-coercion function.
809+
*/
810+
if (coercedTypmod!=NULL)
811+
*coercedTypmod=DatumGetInt32(second_arg->constvalue);
812+
return true;
813+
}
814+
713815
/*
714816
* Produce an appropriate Const node from a constant value produced
715817
* by the parser and an explicit type name to cast to.

‎src/include/parser/parse_expr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parse_expr.h,v 1.16 2000/01/2605:58:27 momjian Exp $
10+
* $Id: parse_expr.h,v 1.17 2000/02/2621:11:09 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -23,5 +23,6 @@
2323
externNode*transformExpr(ParseState*pstate,Node*expr,intprecedence);
2424
externOidexprType(Node*expr);
2525
externint32exprTypmod(Node*expr);
26+
externboolexprIsLengthCoercion(Node*expr,int32*coercedTypmod);
2627

2728
#endif/* PARSE_EXPR_H */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp