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

Commit4952836

Browse files
committed
Create a new parsetree node type, TypeCast, so that transformation of
SQL cast constructs can be performed during expression transformationinstead of during parsing. This allows constructs like x::numeric(9,2)and x::int2::float8 to behave as one would expect.
1 parente0bd601 commit4952836

File tree

10 files changed

+242
-132
lines changed

10 files changed

+242
-132
lines changed

‎src/backend/nodes/copyfuncs.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.99 2000/01/09 00:26:22 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.100 2000/01/17 00:14:46 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1385,6 +1385,17 @@ _copyTypeName(TypeName *from)
13851385
returnnewnode;
13861386
}
13871387

1388+
staticTypeCast*
1389+
_copyTypeCast(TypeCast*from)
1390+
{
1391+
TypeCast*newnode=makeNode(TypeCast);
1392+
1393+
Node_Copy(from,newnode,arg);
1394+
Node_Copy(from,newnode,typename);
1395+
1396+
returnnewnode;
1397+
}
1398+
13881399
staticQuery*
13891400
_copyQuery(Query*from)
13901401
{
@@ -1658,6 +1669,9 @@ copyObject(void *from)
16581669
caseT_TypeName:
16591670
retval=_copyTypeName(from);
16601671
break;
1672+
caseT_TypeCast:
1673+
retval=_copyTypeCast(from);
1674+
break;
16611675

16621676
/*
16631677
* VALUE NODES

‎src/backend/nodes/freefuncs.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.30 2000/01/09 00:26:23 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.31 2000/01/17 00:14:47 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -1046,6 +1046,15 @@ _freeTypeName(TypeName *node)
10461046
pfree(node);
10471047
}
10481048

1049+
staticvoid
1050+
_freeTypeCast(TypeCast*node)
1051+
{
1052+
freeObject(node->arg);
1053+
freeObject(node->typename);
1054+
1055+
pfree(node);
1056+
}
1057+
10491058
staticvoid
10501059
_freeQuery(Query*node)
10511060
{
@@ -1294,6 +1303,9 @@ freeObject(void *node)
12941303
caseT_TypeName:
12951304
_freeTypeName(node);
12961305
break;
1306+
caseT_TypeCast:
1307+
_freeTypeCast(node);
1308+
break;
12971309

12981310
/*
12991311
* VALUE NODES

‎src/backend/nodes/outfuncs.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
*$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.102 2000/01/14 00:53:21 tgl Exp $
8+
*$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.103 2000/01/17 00:14:47 tgl Exp $
99
*
1010
* NOTES
1111
* Every (plan) node in POSTGRES has an associated "out" routine which
@@ -190,6 +190,15 @@ _outTypeName(StringInfo str, TypeName *node)
190190
_outNode(str,node->arrayBounds);
191191
}
192192

193+
staticvoid
194+
_outTypeCast(StringInfostr,TypeCast*node)
195+
{
196+
appendStringInfo(str," TYPECAST :arg ");
197+
_outNode(str,node->arg);
198+
appendStringInfo(str," :typename ");
199+
_outNode(str,node->typename);
200+
}
201+
193202
staticvoid
194203
_outIndexElem(StringInfostr,IndexElem*node)
195204
{
@@ -1292,6 +1301,8 @@ _outAConst(StringInfo str, A_Const *node)
12921301
{
12931302
appendStringInfo(str,"CONST ");
12941303
_outValue(str,&(node->val));
1304+
appendStringInfo(str," :typename ");
1305+
_outNode(str,node->typename);
12951306
}
12961307

12971308
staticvoid
@@ -1400,6 +1411,9 @@ _outNode(StringInfo str, void *obj)
14001411
caseT_TypeName:
14011412
_outTypeName(str,obj);
14021413
break;
1414+
caseT_TypeCast:
1415+
_outTypeCast(str,obj);
1416+
break;
14031417
caseT_IndexElem:
14041418
_outIndexElem(str,obj);
14051419
break;

‎src/backend/parser/gram.y

Lines changed: 40 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
%{ /* -*-text-*- */
1+
%{
22

33
/*#define YYDEBUG 1*/
44
/*-------------------------------------------------------------------------
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.127 2000/01/16 20:04:55 petere Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.128 2000/01/17 00:14:48 tgl Exp $
1414
*
1515
* HISTORY
1616
* AUTHORDATEMAJOR EVENT
@@ -71,6 +71,7 @@ static intpfunc_num_args;
7171
staticchar *xlateSqlFunc(char *);
7272
staticchar *xlateSqlType(char *);
7373
static Node *makeA_Expr(int oper,char *opname, Node *lexpr, Node *rexpr);
74+
static Node *makeTypeCast(Node *arg, TypeName *typename);
7475
static Node *makeRowExpr(char *opr, List *largs, List *rargs);
7576
staticvoidmapTargetColumns(List *source, List *target);
7677
staticvoidparam_type_init(Oid *typev,int nargs);
@@ -274,6 +275,8 @@ static Node *doNegate(Node *n);
274275
* This gets annoying when trying to also retain Postgres' nice
275276
* type-extensible features, but we don't really have a choice.
276277
* - thomas 1997-10-11
278+
* NOTE: Whenever possible, try to add new keywords to the ColId list,
279+
* or failing that, at least to the ColLabel list.
277280
*/
278281

279282
/* Keywords (in SQL92 reserved words)*/
@@ -3902,23 +3905,7 @@ MathOp:'+'{ $$ = "+"; }
39023905
a_expr:com_expr
39033906
{$$ =$1; }
39043907
|a_exprTYPECASTTypename
3905-
{
3906-
$$ = (Node *)$1;
3907-
/* AexprConst can be either A_Const or ParamNo */
3908-
if (nodeTag($1) == T_A_Const) {
3909-
((A_Const *)$1)->typename = $3;
3910-
} else if (nodeTag($1) == T_ParamNo) {
3911-
((ParamNo *)$1)->typename = $3;
3912-
/* otherwise, try to transform to a function call */
3913-
} else {
3914-
FuncCall *n = makeNode(FuncCall);
3915-
n->funcname = $3->name;
3916-
n->args = lcons($1,NIL);
3917-
n->agg_star = false;
3918-
n->agg_distinct = false;
3919-
$$ = (Node *)n;
3920-
}
3921-
}
3908+
{$$ = makeTypeCast($1,$3); }
39223909
/*
39233910
* Can't collapse this into prior rule by using a_expr_or_null;
39243911
* that creates reduce/reduce conflicts. Grumble.
@@ -4149,23 +4136,7 @@ a_expr: com_expr
41494136
b_expr:com_expr
41504137
{$$ =$1; }
41514138
|b_exprTYPECASTTypename
4152-
{
4153-
$$ = (Node *)$1;
4154-
/* AexprConst can be either A_Const or ParamNo */
4155-
if (nodeTag($1) == T_A_Const) {
4156-
((A_Const *)$1)->typename = $3;
4157-
} else if (nodeTag($1) == T_ParamNo) {
4158-
((ParamNo *)$1)->typename = $3;
4159-
/* otherwise, try to transform to a function call */
4160-
} else {
4161-
FuncCall *n = makeNode(FuncCall);
4162-
n->funcname = $3->name;
4163-
n->args = lcons($1,NIL);
4164-
n->agg_star = false;
4165-
n->agg_distinct = false;
4166-
$$ = (Node *)n;
4167-
}
4168-
}
4139+
{$$ = makeTypeCast($1,$3); }
41694140
|NULL_PTYPECASTTypename
41704141
{
41714142
A_Const *n = makeNode(A_Const);
@@ -4243,23 +4214,7 @@ com_expr: attr
42434214
|'('a_expr_or_null')'
42444215
{$$ =$2; }
42454216
|CAST'('a_expr_or_nullASTypename')'
4246-
{
4247-
$$ = (Node *)$3;
4248-
/* AexprConst can be either A_Const or ParamNo */
4249-
if (nodeTag($3) == T_A_Const) {
4250-
((A_Const *)$3)->typename = $5;
4251-
} else if (nodeTag($3) == T_ParamNo) {
4252-
((ParamNo *)$3)->typename = $5;
4253-
/* otherwise, try to transform to a function call */
4254-
} else {
4255-
FuncCall *n = makeNode(FuncCall);
4256-
n->funcname = $5->name;
4257-
n->args = lcons($3,NIL);
4258-
n->agg_star = false;
4259-
n->agg_distinct = false;
4260-
$$ = (Node *)n;
4261-
}
4262-
}
4217+
{$$ = makeTypeCast($3,$5); }
42634218
|case_expr
42644219
{$$ =$1; }
42654220
|func_name'('')'
@@ -5078,6 +5033,7 @@ ColLabel: ColId{ $$ = $1; }
50785033
|CONSTRAINT{$$ ="constraint"; }
50795034
|COPY{$$ ="copy"; }
50805035
|CURRENT{$$ ="current"; }
5036+
|DECIMAL{$$ ="decimal"; }
50815037
|DO{$$ ="do"; }
50825038
|ELSE{$$ ="else"; }
50835039
|END_TRANS{$$ ="end"; }
@@ -5095,6 +5051,7 @@ ColLabel: ColId{ $$ = $1; }
50955051
|NEW{$$ ="new"; }
50965052
|NONE{$$ ="none"; }
50975053
|NULLIF{$$ ="nullif"; }
5054+
|NUMERIC{$$ ="numeric"; }
50985055
|ORDER{$$ ="order"; }
50995056
|POSITION{$$ ="position"; }
51005057
|PRECISION{$$ ="precision"; }
@@ -5139,6 +5096,36 @@ makeA_Expr(int oper, char *opname, Node *lexpr, Node *rexpr)
51395096
return (Node *)a;
51405097
}
51415098

5099+
static Node *
5100+
makeTypeCast(Node *arg, TypeName *typename)
5101+
{
5102+
/*
5103+
* If arg is an A_Const or ParamNo, just stick the typename into the
5104+
* field reserved for it --- unless there's something there already!
5105+
* (We don't want to collapse x::type1::type2 into just x::type2.)
5106+
* Otherwise, generate a TypeCast node.
5107+
*/
5108+
if (IsA(arg, A_Const) &&
5109+
((A_Const *) arg)->typename ==NULL)
5110+
{
5111+
((A_Const *) arg)->typename =typename;
5112+
return arg;
5113+
}
5114+
elseif (IsA(arg, ParamNo) &&
5115+
((ParamNo *) arg)->typename ==NULL)
5116+
{
5117+
((ParamNo *) arg)->typename =typename;
5118+
return arg;
5119+
}
5120+
else
5121+
{
5122+
TypeCast *n =makeNode(TypeCast);
5123+
n->arg = arg;
5124+
n->typename =typename;
5125+
return (Node *) n;
5126+
}
5127+
}
5128+
51425129
/* makeRowExpr()
51435130
* Generate separate operator nodes for a single row descriptor expression.
51445131
* Perhaps this should go deeper in the parser someday...

‎src/backend/parser/parse_coerce.c

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.27 2000/01/10 17:14:36 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.28 2000/01/17 00:14:48 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -32,8 +32,8 @@ static OidPreferredType(CATEGORY category, Oid type);
3232
* Convert a function argument to a different type.
3333
*/
3434
Node*
35-
coerce_type(ParseState*pstate,Node*node,OidinputTypeId,OidtargetTypeId,
36-
int32atttypmod)
35+
coerce_type(ParseState*pstate,Node*node,OidinputTypeId,
36+
OidtargetTypeId,int32atttypmod)
3737
{
3838
Node*result=NULL;
3939

@@ -200,6 +200,70 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids)
200200
return true;
201201
}
202202

203+
/* coerce_type_typmod()
204+
* Force a value to a particular typmod, if meaningful and possible.
205+
*
206+
* This is applied to values that are going to be stored in a relation
207+
* (where we have an atttypmod for the column) as well as values being
208+
* explicitly CASTed (where the typmod comes from the target type spec).
209+
*
210+
* The caller must have already ensured that the value is of the correct
211+
* type, typically by applying coerce_type.
212+
*
213+
* If the target column type possesses a function named for the type
214+
* and having parameter signature (columntype, int4), we assume that
215+
* the type requires coercion to its own length and that the said
216+
* function should be invoked to do that.
217+
*
218+
* "bpchar" (ie, char(N)) and "numeric" are examples of such types.
219+
*/
220+
Node*
221+
coerce_type_typmod(ParseState*pstate,Node*node,
222+
OidtargetTypeId,int32atttypmod)
223+
{
224+
char*funcname;
225+
Oidoid_array[FUNC_MAX_ARGS];
226+
HeapTupleftup;
227+
228+
/*
229+
* We assume that only typmod values greater than 0 indicate a forced
230+
* conversion is necessary.
231+
*/
232+
if (atttypmod <=0||
233+
atttypmod==exprTypmod(node))
234+
returnnode;
235+
236+
funcname=typeidTypeName(targetTypeId);
237+
MemSet(oid_array,0,FUNC_MAX_ARGS*sizeof(Oid));
238+
oid_array[0]=targetTypeId;
239+
oid_array[1]=INT4OID;
240+
241+
/* attempt to find with arguments exactly as specified... */
242+
ftup=SearchSysCacheTuple(PROCNAME,
243+
PointerGetDatum(funcname),
244+
Int32GetDatum(2),
245+
PointerGetDatum(oid_array),
246+
0);
247+
248+
if (HeapTupleIsValid(ftup))
249+
{
250+
A_Const*cons=makeNode(A_Const);
251+
FuncCall*func=makeNode(FuncCall);
252+
253+
cons->val.type=T_Integer;
254+
cons->val.val.ival=atttypmod;
255+
256+
func->funcname=funcname;
257+
func->args=lappend(lcons(node,NIL),cons);
258+
func->agg_star= false;
259+
func->agg_distinct= false;
260+
261+
node=transformExpr(pstate, (Node*)func,EXPR_COLUMN_FIRST);
262+
}
263+
264+
returnnode;
265+
}
266+
203267

204268
/* TypeCategory()
205269
* Assign a category to the specified OID.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp