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

Commitbaeef0e

Browse files
committed
Change rule dumper to produce reasonable output for casts that assign
a specific length or precision, such as foo::char(8). Remove erroneousremoval of user-written casts at the top level of a SELECT target item.
1 parent7173c48 commitbaeef0e

File tree

1 file changed

+82
-92
lines changed

1 file changed

+82
-92
lines changed

‎src/backend/utils/adt/ruleutils.c

Lines changed: 82 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* out of its tuple
44
*
55
* IDENTIFICATION
6-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.43 2000/02/21 20:18:10 tgl Exp $
6+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.44 2000/02/26 21:13:18 tgl Exp $
77
*
88
* This software is copyrighted by Jan Wieck - Hamburg.
99
*
@@ -49,6 +49,7 @@
4949
#include"optimizer/clauses.h"
5050
#include"optimizer/tlist.h"
5151
#include"parser/keywords.h"
52+
#include"parser/parse_expr.h"
5253
#include"parser/parsetree.h"
5354
#include"utils/builtins.h"
5455
#include"utils/lsyscache.h"
@@ -947,7 +948,8 @@ get_select_query_def(Query *query, deparse_context *context)
947948
appendStringInfo(buf,sep);
948949
sep=", ";
949950

950-
get_tle_expr(tle,context);
951+
/* Do NOT use get_tle_expr here; see its comments! */
952+
get_rule_expr(tle->expr,context);
951953

952954
/* Check if we must say AS ... */
953955
if (!IsA(tle->expr,Var))
@@ -1486,16 +1488,16 @@ static void
14861488
get_func_expr(Expr*expr,deparse_context*context)
14871489
{
14881490
StringInfobuf=context->buf;
1491+
Func*func= (Func*) (expr->oper);
14891492
HeapTupleproctup;
14901493
Form_pg_procprocStruct;
1494+
char*proname;
1495+
int32coercedTypmod;
14911496
List*l;
14921497
char*sep;
1493-
Func*func= (Func*) (expr->oper);
1494-
char*proname;
14951498

1496-
/* ----------
1499+
/*
14971500
* Get the functions pg_proc tuple
1498-
* ----------
14991501
*/
15001502
proctup=SearchSysCacheTuple(PROCOID,
15011503
ObjectIdGetDatum(func->funcid),
@@ -1527,9 +1529,59 @@ get_func_expr(Expr *expr, deparse_context *context)
15271529
}
15281530
}
15291531

1530-
/* ----------
1531-
* Build a string of proname(args)
1532-
* ----------
1532+
/*
1533+
* Check to see if function is a length-coercion function for some
1534+
* datatype. If so, display the operation as a type cast.
1535+
*/
1536+
if (exprIsLengthCoercion((Node*)expr,&coercedTypmod))
1537+
{
1538+
Node*arg=lfirst(expr->args);
1539+
1540+
/*
1541+
* Strip off any RelabelType on the input, so we don't print
1542+
* redundancies like x::bpchar::char(8).
1543+
* XXX Are there any cases where this is a bad idea?
1544+
*/
1545+
if (IsA(arg,RelabelType))
1546+
arg= ((RelabelType*)arg)->arg;
1547+
appendStringInfoChar(buf,'(');
1548+
get_rule_expr(arg,context);
1549+
appendStringInfo(buf,")::");
1550+
/*
1551+
* Show typename with appropriate length decoration.
1552+
* Note that since exprIsLengthCoercion succeeded, the function
1553+
* name is the same as its output type name.
1554+
*/
1555+
if (strcmp(proname,"bpchar")==0)
1556+
{
1557+
if (coercedTypmod>VARHDRSZ)
1558+
appendStringInfo(buf,"char(%d)",coercedTypmod-VARHDRSZ);
1559+
else
1560+
appendStringInfo(buf,"char");
1561+
}
1562+
elseif (strcmp(proname,"varchar")==0)
1563+
{
1564+
if (coercedTypmod>VARHDRSZ)
1565+
appendStringInfo(buf,"varchar(%d)",coercedTypmod-VARHDRSZ);
1566+
else
1567+
appendStringInfo(buf,"varchar");
1568+
}
1569+
elseif (strcmp(proname,"numeric")==0)
1570+
{
1571+
if (coercedTypmod >=VARHDRSZ)
1572+
appendStringInfo(buf,"numeric(%d,%d)",
1573+
((coercedTypmod-VARHDRSZ) >>16)&0xffff,
1574+
(coercedTypmod-VARHDRSZ)&0xffff);
1575+
else
1576+
appendStringInfo(buf,"numeric");
1577+
}
1578+
else
1579+
appendStringInfo(buf,"%s",quote_identifier(proname));
1580+
return;
1581+
}
1582+
1583+
/*
1584+
* Normal function: display as proname(args)
15331585
*/
15341586
appendStringInfo(buf,"%s(",quote_identifier(proname));
15351587
sep="";
@@ -1546,99 +1598,37 @@ get_func_expr(Expr *expr, deparse_context *context)
15461598
/* ----------
15471599
* get_tle_expr
15481600
*
1549-
*A target list expression is a bit different from a normal expression.
1550-
*If the target column has an atttypmod, the parser usually puts a
1551-
*padding-/cut-function call around the expression itself.
1552-
*We must get rid of it, otherwise dump/reload/dump... would blow up
1553-
*the expressions.
1601+
*In an INSERT or UPDATE targetlist item, the parser may have inserted
1602+
*a length-coercion function call to coerce the value to the right
1603+
*length for the target column. We want to suppress the output of
1604+
*that function call, otherwise dump/reload/dump... would blow up the
1605+
*expression by adding more and more layers of length-coercion calls.
1606+
*
1607+
* As of 7.0, this hack is no longer absolutely essential, because the parser
1608+
* is now smart enough not to add a redundant length coercion function call.
1609+
* But we still suppress the function call just for neatness of displayed
1610+
* rules.
1611+
*
1612+
* Note that this hack must NOT be applied to SELECT targetlist items;
1613+
* any length coercion appearing there is something the user actually wrote.
15541614
* ----------
15551615
*/
15561616
staticvoid
15571617
get_tle_expr(TargetEntry*tle,deparse_context*context)
15581618
{
15591619
Expr*expr= (Expr*) (tle->expr);
1560-
Func*func;
1561-
HeapTupletup;
1562-
Form_pg_procprocStruct;
1563-
Form_pg_typetypeStruct;
1564-
Const*second_arg;
1565-
1566-
/* ----------
1567-
* Check if the result has an atttypmod and if the
1568-
* expression in the targetlist entry is a function call
1569-
* ----------
1570-
*/
1571-
if (tle->resdom->restypmod<0||
1572-
!IsA(expr,Expr)||
1573-
expr->opType!=FUNC_EXPR)
1574-
{
1575-
get_rule_expr(tle->expr,context);
1576-
return;
1577-
}
1578-
1579-
func= (Func*) (expr->oper);
1580-
1581-
/* ----------
1582-
* Get the functions pg_proc tuple
1583-
* ----------
1584-
*/
1585-
tup=SearchSysCacheTuple(PROCOID,
1586-
ObjectIdGetDatum(func->funcid),0,0,0);
1587-
if (!HeapTupleIsValid(tup))
1588-
elog(ERROR,"cache lookup for proc %u failed",func->funcid);
1589-
procStruct= (Form_pg_proc)GETSTRUCT(tup);
1590-
1591-
/* ----------
1592-
* It must be a function with two arguments where the first
1593-
* is of the same type as the return value and the second is
1594-
* an int4.
1595-
* ----------
1596-
*/
1597-
if (procStruct->pronargs!=2||
1598-
procStruct->prorettype!=procStruct->proargtypes[0]||
1599-
procStruct->proargtypes[1]!=INT4OID)
1600-
{
1601-
get_rule_expr(tle->expr,context);
1602-
return;
1603-
}
1620+
int32coercedTypmod;
16041621

16051622
/*
1606-
* Furthermore, the name of the function must be the same
1607-
* as the argument/result type name.
1608-
*/
1609-
tup=SearchSysCacheTuple(TYPEOID,
1610-
ObjectIdGetDatum(procStruct->prorettype),
1611-
0,0,0);
1612-
if (!HeapTupleIsValid(tup))
1613-
elog(ERROR,"cache lookup for type %u failed",
1614-
procStruct->prorettype);
1615-
typeStruct= (Form_pg_type)GETSTRUCT(tup);
1616-
if (strncmp(NameStr(procStruct->proname),
1617-
NameStr(typeStruct->typname),
1618-
NAMEDATALEN)!=0)
1619-
{
1620-
get_rule_expr(tle->expr,context);
1621-
return;
1622-
}
1623-
1624-
/* ----------
1625-
* Finally (to be totally safe) the second argument must be a
1626-
* const and match the value in the results atttypmod.
1627-
* ----------
1623+
* If top level is a length coercion to the correct length, suppress it;
1624+
* else dump the expression normally.
16281625
*/
1629-
second_arg= (Const*)lsecond(expr->args);
1630-
if (!IsA(second_arg,Const)||
1631-
DatumGetInt32(second_arg->constvalue)!=tle->resdom->restypmod)
1632-
{
1626+
if (tle->resdom->restypmod >=0&&
1627+
exprIsLengthCoercion((Node*)expr,&coercedTypmod)&&
1628+
coercedTypmod==tle->resdom->restypmod)
1629+
get_rule_expr((Node*)lfirst(expr->args),context);
1630+
else
16331631
get_rule_expr(tle->expr,context);
1634-
return;
1635-
}
1636-
1637-
/* ----------
1638-
* Whow - got it. Now get rid of the padding function
1639-
* ----------
1640-
*/
1641-
get_rule_expr((Node*)lfirst(expr->args),context);
16421632
}
16431633

16441634

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp