Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
3ace5fd0
Commit
3ace5fd0
authored
May 09, 1998
by
Thomas G. Lockhart
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add capabilities for automatic type conversion.
parent
54b5577c
Changes
10
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
2050 additions
and
394 deletions
+2050
-394
src/backend/parser/analyze.c
src/backend/parser/analyze.c
+8
-1
src/backend/parser/parse_coerce.c
src/backend/parser/parse_coerce.c
+560
-0
src/backend/parser/parse_expr.c
src/backend/parser/parse_expr.c
+12
-6
src/backend/parser/parse_func.c
src/backend/parser/parse_func.c
+727
-119
src/backend/parser/parse_node.c
src/backend/parser/parse_node.c
+115
-42
src/backend/parser/parse_oper.c
src/backend/parser/parse_oper.c
+341
-128
src/backend/parser/parse_target.c
src/backend/parser/parse_target.c
+181
-94
src/backend/parser/parse_type.c
src/backend/parser/parse_type.c
+8
-2
src/include/parser/parse_coerce.h
src/include/parser/parse_coerce.h
+96
-0
src/include/parser/parse_func.h
src/include/parser/parse_func.h
+2
-2
No files found.
src/backend/parser/analyze.c
View file @
3ace5fd0
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.7
4 1998/03/31 23:31:10 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.7
5 1998/05/09 23:29:52 thomas
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -30,6 +30,9 @@
...
@@ -30,6 +30,9 @@
#include "parser/parse_target.h"
#include "parser/parse_target.h"
#include "utils/builtins.h"
#include "utils/builtins.h"
#include "utils/mcxt.h"
#include "utils/mcxt.h"
#ifdef PARSEDEBUG
#include "nodes/print.h"
#endif
static
Query
*
transformStmt
(
ParseState
*
pstate
,
Node
*
stmt
);
static
Query
*
transformStmt
(
ParseState
*
pstate
,
Node
*
stmt
);
static
Query
*
transformDeleteStmt
(
ParseState
*
pstate
,
DeleteStmt
*
stmt
);
static
Query
*
transformDeleteStmt
(
ParseState
*
pstate
,
DeleteStmt
*
stmt
);
...
@@ -65,6 +68,10 @@ parse_analyze(List *pl, ParseState *parentParseState)
...
@@ -65,6 +68,10 @@ parse_analyze(List *pl, ParseState *parentParseState)
while
(
pl
!=
NIL
)
while
(
pl
!=
NIL
)
{
{
#ifdef PARSEDEBUG
elog
(
DEBUG
,
"parse tree from yacc:
\n
---
\n
%s
\n
---
\n
"
,
nodeToString
(
lfirst
(
pl
)));
#endif
pstate
=
make_parsestate
(
parentParseState
);
pstate
=
make_parsestate
(
parentParseState
);
result
->
qtrees
[
i
++
]
=
transformStmt
(
pstate
,
lfirst
(
pl
));
result
->
qtrees
[
i
++
]
=
transformStmt
(
pstate
,
lfirst
(
pl
));
if
(
pstate
->
p_target_relation
!=
NULL
)
if
(
pstate
->
p_target_relation
!=
NULL
)
...
...
src/backend/parser/parse_coerce.c
0 → 100644
View file @
3ace5fd0
This diff is collapsed.
Click to expand it.
src/backend/parser/parse_expr.c
View file @
3ace5fd0
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.2
7 1998/04/26 04:06:45 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.2
8 1998/05/09 23:29:53 thomas
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -301,12 +301,14 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
...
@@ -301,12 +301,14 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
result
=
(
Node
*
)
expr
;
result
=
(
Node
*
)
expr
;
break
;
break
;
}
}
/* These nodes do _not_ come from the original parse tree.
* They result from parser transformation in this phase.
/* These nodes do _not_ come from the original parse tree,
* but result from parser transformation in this phase.
* At least one construct (BETWEEN/AND) puts the same nodes
* At least one construct (BETWEEN/AND) puts the same nodes
* into two branches of the parse tree. Hence, some nodes
* into two branches of the parse tree; hence, some nodes
* are transformed twice. These nodes come from transforming
* are transformed twice.
* a function call. Let's try just passing them through...
* These cases below come from transforming function calls.
* Let's try just passing them through...
* - thomas 1998-03-14
* - thomas 1998-03-14
*/
*/
case
T_Expr
:
case
T_Expr
:
...
@@ -506,6 +508,10 @@ parser_typecast(Value *expr, TypeName *typename, int16 atttypmod)
...
@@ -506,6 +508,10 @@ parser_typecast(Value *expr, TypeName *typename, int16 atttypmod)
return
(
Node
*
)
adt
;
return
(
Node
*
)
adt
;
}
}
/* parser_typecast2()
* Convert (only) constants to specified type.
*/
Node
*
Node
*
parser_typecast2
(
Node
*
expr
,
Oid
exprType
,
Type
tp
,
int16
atttypmod
)
parser_typecast2
(
Node
*
expr
,
Oid
exprType
,
Type
tp
,
int16
atttypmod
)
{
{
...
...
src/backend/parser/parse_func.c
View file @
3ace5fd0
This diff is collapsed.
Click to expand it.
src/backend/parser/parse_node.c
View file @
3ace5fd0
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.1
4 1998/02/26 04:33:32 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.1
5 1998/05/09 23:29:53 thomas
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -39,7 +39,7 @@ make_operand(char *opname,
...
@@ -39,7 +39,7 @@ make_operand(char *opname,
/*
/*
* make_parsestate() --
* make_parsestate() --
* allocate and initialize a new ParseState.
* allocate and initialize a new ParseState.
* the CALLER
S
is responsible for freeing the ParseState* returned
* the CALLER is responsible for freeing the ParseState* returned
*
*
*/
*/
...
@@ -57,6 +57,15 @@ make_parsestate(ParseState *parentParseState)
...
@@ -57,6 +57,15 @@ make_parsestate(ParseState *parentParseState)
return
(
pstate
);
return
(
pstate
);
}
}
extern
Node
*
coerce_type
(
ParseState
*
pstate
,
Node
*
node
,
Oid
inputTypeId
,
Oid
targetTypeId
);
/* make_operand()
* Ensure argument type match by forcing conversion of constants.
*/
static
Node
*
static
Node
*
make_operand
(
char
*
opname
,
make_operand
(
char
*
opname
,
Node
*
tree
,
Node
*
tree
,
...
@@ -65,35 +74,33 @@ make_operand(char *opname,
...
@@ -65,35 +74,33 @@ make_operand(char *opname,
{
{
Node
*
result
;
Node
*
result
;
Type
true_type
;
Type
true_type
;
#if FALSE
Datum
val
;
Datum
val
;
Oid
infunc
;
Oid
infunc
;
#endif
#ifdef PARSEDEBUG
printf
(
"make_operand: constructing operand for '%s' %s->%s
\n
"
,
opname
,
typeidTypeName
(
orig_typeId
),
typeidTypeName
(
true_typeId
));
#endif
if
(
tree
!=
NULL
)
if
(
tree
!=
NULL
)
{
{
result
=
tree
;
result
=
tree
;
true_type
=
typeidType
(
true_typeId
);
true_type
=
typeidType
(
true_typeId
);
disallow_setop
(
opname
,
true_type
,
result
);
disallow_setop
(
opname
,
true_type
,
result
);
/* must coerce? */
if
(
true_typeId
!=
orig_typeId
)
if
(
true_typeId
!=
orig_typeId
)
{
/* must coerce */
{
Const
*
con
=
(
Const
*
)
result
;
#ifdef PARSEDEBUG
printf
(
"make_operand: try to convert node from %s to %s
\n
"
,
Assert
(
nodeTag
(
result
)
==
T_Const
);
typeidTypeName
(
orig_typeId
),
typeidTypeName
(
true_typeId
));
val
=
(
Datum
)
textout
((
struct
varlena
*
)
#endif
con
->
constvalue
);
result
=
coerce_type
(
NULL
,
tree
,
orig_typeId
,
true_typeId
);
infunc
=
typeidInfunc
(
true_typeId
);
con
=
makeNode
(
Const
);
con
->
consttype
=
true_typeId
;
con
->
constlen
=
typeLen
(
true_type
);
con
->
constvalue
=
(
Datum
)
fmgr
(
infunc
,
val
,
typeidTypElem
(
true_typeId
),
-
1
/* for varchar() type */
);
con
->
constisnull
=
false
;
con
->
constbyval
=
true
;
con
->
constisset
=
false
;
result
=
(
Node
*
)
con
;
}
}
}
}
/* otherwise, this is a NULL value */
else
else
{
{
Const
*
con
=
makeNode
(
Const
);
Const
*
con
=
makeNode
(
Const
);
...
@@ -108,7 +115,7 @@ make_operand(char *opname,
...
@@ -108,7 +115,7 @@ make_operand(char *opname,
}
}
return
result
;
return
result
;
}
}
/* make_operand() */
static
void
static
void
...
@@ -119,13 +126,49 @@ disallow_setop(char *op, Type optype, Node *operand)
...
@@ -119,13 +126,49 @@ disallow_setop(char *op, Type optype, Node *operand)
if
(
nodeTag
(
operand
)
==
T_Iter
)
if
(
nodeTag
(
operand
)
==
T_Iter
)
{
{
elog
(
NOTICE
,
"An operand to the '%s' operator returns a set of %s,"
,
elog
(
ERROR
,
"An operand to the '%s' operator returns a set of %s,"
op
,
typeTypeName
(
optype
));
"
\n\t
but '%s' takes single values, not sets."
,
elog
(
ERROR
,
"but '%s' takes single values, not sets."
,
op
,
typeTypeName
(
optype
),
op
);
op
);
}
}
}
}
/* CoerceType()
* Try to force type of node.
*/
Oid
CoerceType
(
Oid
typeId
,
Node
*
node
);
Oid
CoerceType
(
Oid
typeId
,
Node
*
node
)
{
switch
(
nodeTag
(
node
))
{
case
T_Const
:
{
Const
*
con
=
(
Const
*
)
node
;
#ifdef PARSEDEBUG
printf
(
"Convert node %d to text
\n
"
,
nodeTag
(
node
));
#endif
typeId
=
TEXTOID
;
con
->
consttype
=
typeId
;
}
break
;
default:
break
;
}
return
typeId
;
}
/* CoerceType() */
/* make_op()
* Operator construction.
*
* Transform operator expression ensuring type compatibility.
* This is where some type conversion happens.
*/
Expr
*
Expr
*
make_op
(
char
*
opname
,
Node
*
ltree
,
Node
*
rtree
)
make_op
(
char
*
opname
,
Node
*
ltree
,
Node
*
rtree
)
{
{
...
@@ -138,10 +181,9 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -138,10 +181,9 @@ make_op(char *opname, Node *ltree, Node *rtree)
*
right
;
*
right
;
Expr
*
result
;
Expr
*
result
;
/* right operator? */
if
(
rtree
==
NULL
)
if
(
rtree
==
NULL
)
{
{
/* right operator */
ltypeId
=
(
ltree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
ltree
);
ltypeId
=
(
ltree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
ltree
);
temp
=
right_oper
(
opname
,
ltypeId
);
temp
=
right_oper
(
opname
,
ltypeId
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
...
@@ -149,25 +191,29 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -149,25 +191,29 @@ make_op(char *opname, Node *ltree, Node *rtree)
right
=
NULL
;
right
=
NULL
;
}
}
/* left operator? */
else
if
(
ltree
==
NULL
)
else
if
(
ltree
==
NULL
)
{
{
/* left operator */
rtypeId
=
(
rtree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
rtree
);
rtypeId
=
(
rtree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
rtree
);
temp
=
left_oper
(
opname
,
rtypeId
);
temp
=
left_oper
(
opname
,
rtypeId
);
#ifdef PARSEDEBUG
printf
(
"make_op: returned from left_oper() with structure at %p
\n
"
,
(
void
*
)
temp
);
#endif
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
#ifdef PARSEDEBUG
printf
(
"make_op: calling make_operand()
\n
"
);
#endif
right
=
make_operand
(
opname
,
rtree
,
rtypeId
,
opform
->
oprright
);
right
=
make_operand
(
opname
,
rtree
,
rtypeId
,
opform
->
oprright
);
left
=
NULL
;
left
=
NULL
;
}
}
/* otherwise, binary operator */
else
else
{
{
char
*
outstr
;
Oid
infunc
,
outfunc
;
Type
newtype
;
#define CONVERT
A
BLE_TYPE(t) ( (t) == INT2OID || \
#define CONVERT
I
BLE_TYPE(t) ( (t) == INT2OID || \
(t) == INT4OID || \
(t) == INT4OID || \
(t) == OIDOID || \
(t) == OIDOID || \
(t) == FLOAT4OID || \
(t) == FLOAT4OID || \
...
@@ -178,12 +224,32 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -178,12 +224,32 @@ make_op(char *opname, Node *ltree, Node *rtree)
ltypeId
=
(
ltree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
ltree
);
ltypeId
=
(
ltree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
ltree
);
rtypeId
=
(
rtree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
rtree
);
rtypeId
=
(
rtree
==
NULL
)
?
UNKNOWNOID
:
exprType
(
rtree
);
#if FALSE
/* Both operands of unknown type?
* Then they are strings and we should force at least one to text
* - thomas 1998-03-16
*/
ltypeId
=
exprType
(
ltree
);
rtypeId
=
exprType
(
rtree
);
if
((
ltypeId
==
UNKNOWNOID
)
&&
(
rtypeId
==
UNKNOWNOID
))
{
#ifdef PARSEDEBUG
printf
(
"Convert left-hand constant to text for node %d
\n
"
,
nodeTag
(
ltree
));
#endif
ltypeId
=
CoerceType
(
TEXTOID
,
ltree
);
}
#endif
#if FALSE
/*
/*
* convert constant when using a const of a numeric type and a
* convert constant when using a const of a numeric type and a
* non-const of another numeric type
* non-const of another numeric type
*/
*/
if
(
CONVERT
A
BLE_TYPE
(
ltypeId
)
&&
nodeTag
(
ltree
)
!=
T_Const
&&
if
(
CONVERT
I
BLE_TYPE
(
ltypeId
)
&&
nodeTag
(
ltree
)
!=
T_Const
&&
CONVERT
A
BLE_TYPE
(
rtypeId
)
&&
nodeTag
(
rtree
)
==
T_Const
&&
CONVERT
I
BLE_TYPE
(
rtypeId
)
&&
nodeTag
(
rtree
)
==
T_Const
&&
!
((
Const
*
)
rtree
)
->
constiscast
)
!
((
Const
*
)
rtree
)
->
constiscast
)
{
{
outfunc
=
typeidOutfunc
(
rtypeId
);
outfunc
=
typeidOutfunc
(
rtypeId
);
...
@@ -197,8 +263,8 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -197,8 +263,8 @@ make_op(char *opname, Node *ltree, Node *rtree)
((
Const
*
)
rtree
)
->
constbyval
=
typeByVal
(
newtype
);
((
Const
*
)
rtree
)
->
constbyval
=
typeByVal
(
newtype
);
}
}
if
(
CONVERT
A
BLE_TYPE
(
rtypeId
)
&&
nodeTag
(
rtree
)
!=
T_Const
&&
if
(
CONVERT
I
BLE_TYPE
(
rtypeId
)
&&
nodeTag
(
rtree
)
!=
T_Const
&&
CONVERT
A
BLE_TYPE
(
ltypeId
)
&&
nodeTag
(
ltree
)
==
T_Const
&&
CONVERT
I
BLE_TYPE
(
ltypeId
)
&&
nodeTag
(
ltree
)
==
T_Const
&&
!
((
Const
*
)
ltree
)
->
constiscast
)
!
((
Const
*
)
ltree
)
->
constiscast
)
{
{
outfunc
=
typeidOutfunc
(
ltypeId
);
outfunc
=
typeidOutfunc
(
ltypeId
);
...
@@ -211,6 +277,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -211,6 +277,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
((
Const
*
)
ltree
)
->
constlen
=
typeLen
(
newtype
);
((
Const
*
)
ltree
)
->
constlen
=
typeLen
(
newtype
);
((
Const
*
)
ltree
)
->
constbyval
=
typeByVal
(
newtype
);
((
Const
*
)
ltree
)
->
constbyval
=
typeByVal
(
newtype
);
}
}
#endif
temp
=
oper
(
opname
,
ltypeId
,
rtypeId
,
false
);
temp
=
oper
(
opname
,
ltypeId
,
rtypeId
,
false
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
opform
=
(
OperatorTupleForm
)
GETSTRUCT
(
temp
);
...
@@ -219,7 +286,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -219,7 +286,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
}
}
newop
=
makeOper
(
oprid
(
temp
),
/* opno */
newop
=
makeOper
(
oprid
(
temp
),
/* opno */
InvalidOid
,
/* opid */
InvalidOid
,
/* opid */
opform
->
oprresult
,
/* operator result type */
opform
->
oprresult
,
/* operator result type */
0
,
0
,
NULL
);
NULL
);
...
@@ -239,6 +306,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
...
@@ -239,6 +306,7 @@ make_op(char *opname, Node *ltree, Node *rtree)
return
result
;
return
result
;
}
}
Var
*
Var
*
make_var
(
ParseState
*
pstate
,
Oid
relid
,
char
*
refname
,
make_var
(
ParseState
*
pstate
,
Oid
relid
,
char
*
refname
,
char
*
attrname
)
char
*
attrname
)
...
@@ -356,6 +424,9 @@ make_array_ref(Node *expr,
...
@@ -356,6 +424,9 @@ make_array_ref(Node *expr,
return
aref
;
return
aref
;
}
}
/* make_array_set()
*/
ArrayRef
*
ArrayRef
*
make_array_set
(
Expr
*
target_expr
,
make_array_set
(
Expr
*
target_expr
,
List
*
upperIndexpr
,
List
*
upperIndexpr
,
...
@@ -406,10 +477,12 @@ make_array_set(Expr *target_expr,
...
@@ -406,10 +477,12 @@ make_array_set(Expr *target_expr,
aref
->
refexpr
=
(
Node
*
)
target_expr
;
aref
->
refexpr
=
(
Node
*
)
target_expr
;
aref
->
refassgnexpr
=
(
Node
*
)
expr
;
aref
->
refassgnexpr
=
(
Node
*
)
expr
;
if
(
lowerIndexpr
==
NIL
)
/* accessing a single array element */
/* accessing a single array element? */
if
(
lowerIndexpr
==
NIL
)
reftype
=
aref
->
refelemtype
;
reftype
=
aref
->
refelemtype
;
/* otherwise, request to set a part of the array, by another array */
else
else
/* request to set a part of the array, by another array */
reftype
=
typearray
;
reftype
=
typearray
;
aref
->
refelemtype
=
reftype
;
aref
->
refelemtype
=
reftype
;
...
...
src/backend/parser/parse_oper.c
View file @
3ace5fd0
This diff is collapsed.
Click to expand it.
src/backend/parser/parse_target.c
View file @
3ace5fd0
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.1
1 1998/02/26 04:33:35 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.1
2 1998/05/09 23:29:54 thomas
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -26,6 +26,13 @@
...
@@ -26,6 +26,13 @@
#include "parser/parse_target.h"
#include "parser/parse_target.h"
#include "utils/builtins.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
extern
bool
can_coerce_type
(
int
nargs
,
Oid
*
input_typeids
,
Oid
*
func_typeids
);
extern
Node
*
coerce_type
(
ParseState
*
pstate
,
Node
*
node
,
Oid
inputTypeId
,
Oid
targetTypeId
);
static
List
*
expandAllTables
(
ParseState
*
pstate
);
static
List
*
expandAllTables
(
ParseState
*
pstate
);
static
char
*
figureColname
(
Node
*
expr
,
Node
*
resval
);
static
char
*
figureColname
(
Node
*
expr
,
Node
*
resval
);
...
@@ -34,6 +41,16 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -34,6 +41,16 @@ make_targetlist_expr(ParseState *pstate,
char
*
colname
,
char
*
colname
,
Node
*
expr
,
Node
*
expr
,
List
*
arrayRef
);
List
*
arrayRef
);
Node
*
size_target_expr
(
ParseState
*
pstate
,
Node
*
expr
,
Oid
attrtype
,
int16
attrtypmod
);
Node
*
coerce_target_expr
(
ParseState
*
pstate
,
Node
*
expr
,
Oid
type_id
,
Oid
attrtype
);
/*
/*
* transformTargetList -
* transformTargetList -
...
@@ -110,8 +127,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
...
@@ -110,8 +127,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
Relation
rd
;
Relation
rd
;
Value
*
constval
;
Value
*
constval
;
if
(
exprType
(
expr
)
!=
UNKNOWNOID
||
if
(
exprType
(
expr
)
!=
UNKNOWNOID
||
!
IsA
(
expr
,
Const
))
!
IsA
(
expr
,
Const
))
elog
(
ERROR
,
"yyparse: string constant expected"
);
elog
(
ERROR
,
"yyparse: string constant expected"
);
val
=
(
char
*
)
textout
((
struct
varlena
*
)
val
=
(
char
*
)
textout
((
struct
varlena
*
)
...
@@ -123,15 +139,15 @@ transformTargetList(ParseState *pstate, List *targetlist)
...
@@ -123,15 +139,15 @@ transformTargetList(ParseState *pstate, List *targetlist)
aind
->
uidx
=
transformExpr
(
pstate
,
aind
->
uidx
,
EXPR_COLUMN_FIRST
);
aind
->
uidx
=
transformExpr
(
pstate
,
aind
->
uidx
,
EXPR_COLUMN_FIRST
);
if
(
!
IsA
(
aind
->
uidx
,
Const
))
if
(
!
IsA
(
aind
->
uidx
,
Const
))
elog
(
ERROR
,
elog
(
ERROR
,
"Array Index for Append should be a constant"
);
"Array Index for Append should be a constant"
);
uindx
[
i
]
=
((
Const
*
)
aind
->
uidx
)
->
constvalue
;
uindx
[
i
]
=
((
Const
*
)
aind
->
uidx
)
->
constvalue
;
if
(
aind
->
lidx
!=
NULL
)
if
(
aind
->
lidx
!=
NULL
)
{
{
aind
->
lidx
=
transformExpr
(
pstate
,
aind
->
lidx
,
EXPR_COLUMN_FIRST
);
aind
->
lidx
=
transformExpr
(
pstate
,
aind
->
lidx
,
EXPR_COLUMN_FIRST
);
if
(
!
IsA
(
aind
->
lidx
,
Const
))
if
(
!
IsA
(
aind
->
lidx
,
Const
))
elog
(
ERROR
,
elog
(
ERROR
,
"Array Index for Append should be a constant"
);
"Array Index for Append should be a constant"
);
lindx
[
i
]
=
((
Const
*
)
aind
->
lidx
)
->
constvalue
;
lindx
[
i
]
=
((
Const
*
)
aind
->
lidx
)
->
constvalue
;
}
}
else
else
...
@@ -140,6 +156,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
...
@@ -140,6 +156,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
}
}
if
(
lindx
[
i
]
>
uindx
[
i
])
if
(
lindx
[
i
]
>
uindx
[
i
])
elog
(
ERROR
,
"yyparse: lower index cannot be greater than upper index"
);
elog
(
ERROR
,
"yyparse: lower index cannot be greater than upper index"
);
sprintf
(
str
,
"[%d:%d]"
,
lindx
[
i
],
uindx
[
i
]);
sprintf
(
str
,
"[%d:%d]"
,
lindx
[
i
],
uindx
[
i
]);
str
+=
strlen
(
str
);
str
+=
strlen
(
str
);
i
++
;
i
++
;
...
@@ -151,6 +168,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
...
@@ -151,6 +168,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
ndims
=
attnumAttNelems
(
rd
,
resdomno
);
ndims
=
attnumAttNelems
(
rd
,
resdomno
);
if
(
i
!=
ndims
)
if
(
i
!=
ndims
)
elog
(
ERROR
,
"yyparse: array dimensions do not match"
);
elog
(
ERROR
,
"yyparse: array dimensions do not match"
);
constval
=
makeNode
(
Value
);
constval
=
makeNode
(
Value
);
constval
->
type
=
T_String
;
constval
->
type
=
T_String
;
constval
->
val
.
str
=
save_str
;
constval
->
val
.
str
=
save_str
;
...
@@ -300,8 +318,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
...
@@ -300,8 +318,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
}
}
default:
default:
/* internal error */
/* internal error */
elog
(
ERROR
,
elog
(
ERROR
,
"internal error: do not know how to transform targetlist"
);
"internal error: do not know how to transform targetlist"
);
break
;
break
;
}
}
...
@@ -321,11 +338,125 @@ transformTargetList(ParseState *pstate, List *targetlist)
...
@@ -321,11 +338,125 @@ transformTargetList(ParseState *pstate, List *targetlist)
}
}
/*
Node
*
* make_targetlist_expr -
coerce_target_expr
(
ParseState
*
pstate
,
* make a TargetEntry from an expression
Node
*
expr
,
Oid
type_id
,
Oid
attrtype
)
{
if
(
can_coerce_type
(
1
,
&
type_id
,
&
attrtype
))
{
#ifdef PARSEDEBUG
printf
(
"parse_target: coerce type from %s to %s
\n
"
,
typeidTypeName
(
type_id
),
typeidTypeName
(
attrtype
));
#endif
expr
=
coerce_type
(
pstate
,
expr
,
type_id
,
attrtype
);
}
#ifndef DISABLE_STRING_HACKS
/* string hacks to get transparent conversions w/o explicit conversions */
else
if
((
attrtype
==
BPCHAROID
)
||
(
attrtype
==
VARCHAROID
))
{
Oid
text_id
=
TEXTOID
;
#ifdef PARSEDEBUG
printf
(
"parse_target: try coercing from %s to %s via text
\n
"
,
typeidTypeName
(
type_id
),
typeidTypeName
(
attrtype
));
#endif
if
(
type_id
==
TEXTOID
)
{
}
else
if
(
can_coerce_type
(
1
,
&
type_id
,
&
text_id
))
{
expr
=
coerce_type
(
pstate
,
expr
,
type_id
,
text_id
);
}
else
{
expr
=
NULL
;
}
}
#endif
else
{
expr
=
NULL
;
}
return
expr
;
}
/* coerce_target_expr() */
/* size_target_expr()
* Apparently going to a fixed-length string?
* Then explicitly size for storage...
*/
Node
*
size_target_expr
(
ParseState
*
pstate
,
Node
*
expr
,
Oid
attrtype
,
int16
attrtypmod
)
{
int
i
;
HeapTuple
ftup
;
char
*
funcname
;
Oid
oid_array
[
8
];
FuncCall
*
func
;
A_Const
*
cons
;
#ifdef PARSEDEBUG
printf
(
"parse_target: ensure target fits storage
\n
"
);
#endif
funcname
=
typeidTypeName
(
attrtype
);
oid_array
[
0
]
=
attrtype
;
oid_array
[
1
]
=
INT4OID
;
for
(
i
=
2
;
i
<
8
;
i
++
)
oid_array
[
i
]
=
InvalidOid
;
#ifdef PARSEDEBUG
printf
(
"parse_target: look for conversion function %s(%s,%s)
\n
"
,
funcname
,
typeidTypeName
(
attrtype
),
typeidTypeName
(
INT4OID
));
#endif
/* attempt to find with arguments exactly as specified... */
ftup
=
SearchSysCacheTuple
(
PRONAME
,
PointerGetDatum
(
funcname
),
Int32GetDatum
(
2
),
PointerGetDatum
(
oid_array
),
0
);
if
(
HeapTupleIsValid
(
ftup
))
{
#ifdef PARSEDEBUG
printf
(
"parse_target: found conversion function for sizing
\n
"
);
#endif
func
=
makeNode
(
FuncCall
);
func
->
funcname
=
funcname
;
cons
=
makeNode
(
A_Const
);
cons
->
val
.
type
=
T_Integer
;
cons
->
val
.
val
.
ival
=
attrtypmod
;
func
->
args
=
lappend
(
lcons
(
expr
,
NIL
),
cons
);
expr
=
transformExpr
(
pstate
,
(
Node
*
)
func
,
EXPR_COLUMN_FIRST
);
}
#ifdef PARSEDEBUG
else
{
printf
(
"parse_target: no conversion function for sizing
\n
"
);
}
#endif
return
expr
;
}
/* size_target_expr() */
/* make_targetlist_expr()
* Make a TargetEntry from an expression
*
*
* arrayRef is a list of transformed A_Indices
* arrayRef is a list of transformed A_Indices
*
* For type mismatches between expressions and targets, use the same
* techniques as for function and operator type coersion.
* - thomas 1998-05-08
*/
*/
static
TargetEntry
*
static
TargetEntry
*
make_targetlist_expr
(
ParseState
*
pstate
,
make_targetlist_expr
(
ParseState
*
pstate
,
...
@@ -355,7 +486,6 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -355,7 +486,6 @@ make_targetlist_expr(ParseState *pstate,
/* Processes target columns that will be receiving results */
/* Processes target columns that will be receiving results */
if
(
pstate
->
p_is_insert
||
pstate
->
p_is_update
)
if
(
pstate
->
p_is_insert
||
pstate
->
p_is_update
)
{
{
/*
/*
* insert or update query -- insert, update work only on one
* insert or update query -- insert, update work only on one
* relation, so multiple occurence of same resdomno is bogus
* relation, so multiple occurence of same resdomno is bogus
...
@@ -368,91 +498,47 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -368,91 +498,47 @@ make_targetlist_expr(ParseState *pstate,
if
((
arrayRef
!=
NIL
)
&&
(
lfirst
(
arrayRef
)
==
NIL
))
if
((
arrayRef
!=
NIL
)
&&
(
lfirst
(
arrayRef
)
==
NIL
))
attrtype
=
GetArrayElementType
(
attrtype
);
attrtype
=
GetArrayElementType
(
attrtype
);
attrtypmod
=
rd
->
rd_att
->
attrs
[
resdomno
-
1
]
->
atttypmod
;
attrtypmod
=
rd
->
rd_att
->
attrs
[
resdomno
-
1
]
->
atttypmod
;
#if 0
if (Input_is_string && Typecast_ok)
{
Datum val;
if (type_id == typeTypeId(type("unknown")))
/* Check for InvalidOid since that seems to indicate a NULL constant... */
if
(
type_id
!=
InvalidOid
)
{
{
val = (Datum) textout((struct varlena *)
/* Mismatch on types? then try to coerce to target... */
((Const) lnext(expr))->constvalue);
if
(
attrtype
!=
type_id
)
}
else
{
{
val = ((Const) lnext(expr))->constvalue
;
Oid
typelem
;
}
if (attrisset
)
if
(
arrayRef
&&
!
(((
A_Indices
*
)
lfirst
(
arrayRef
))
->
lidx
)
)
{
{
lnext(expr) = makeConst(attrtype,
typelem
=
typeidTypElem
(
attrtype
);
attrlen,
val,
false,
true,
true, /* is set */
false);
}
}
else
else
{
{
lnext(expr) =
typelem
=
attrtype
;
makeConst(attrtype,
attrlen,
(Datum) fmgr(typeidInfunc(attrtype),
val, typeidTypElem(attrtype), -1),
false,
true /* Maybe correct-- 80% chance */ ,
false, /* is not a set */
false);
}
}
}
else if ((Typecast_ok) && (attrtype != type_id))
expr
=
coerce_target_expr
(
pstate
,
expr
,
type_id
,
typelem
);
if
(
!
HeapTupleIsValid
(
expr
))
{
{
lnext(expr) =
elog
(
ERROR
,
"parser: attribute '%s' is of type '%s'"
parser_typecast2(expr, typeidType(attrtype));
" but expression is of type '%s'"
"
\n\t
You will need to rewrite or cast the expression"
,
colname
,
typeidTypeName
(
attrtype
),
typeidTypeName
(
type_id
));
}
}
else if (attrtype != type_id)
{
if ((attrtype == INT2OID) && (type_id == INT4OID))
lfirst(expr) = lispInteger(INT2OID); /* handle CASHOID too */
else if ((attrtype == FLOAT4OID) && (type_id == FLOAT8OID))
lfirst(expr) = lispInteger(FLOAT4OID);
else
elog(ERROR, "unequal type in tlist : %s \n", colname);
}
}
Input_is_string = false;
#ifdef PARSEDEBUG
Input_is_integer = false;
printf
(
"parse_target: attrtypmod is %d
\n
"
,
(
int4
)
attrtypmod
);
Typecast_ok = true;
#endif
#endif
if
(
attrtype
!=
type_id
)
/* Apparently going to a fixed-length string?
{
* Then explicitly size for storage...
if
(
IsA
(
expr
,
Const
))
*/
{
if
(
attrtypmod
>
0
)
/* try to cast the constant */
if
(
arrayRef
&&
!
(((
A_Indices
*
)
lfirst
(
arrayRef
))
->
lidx
))
{
/* updating a single item */
Oid
typelem
=
typeidTypElem
(
attrtype
);
expr
=
(
Node
*
)
parser_typecast2
(
expr
,
type_id
,
typeidType
(
typelem
),
attrtypmod
);
}
else
expr
=
(
Node
*
)
parser_typecast2
(
expr
,
type_id
,
typeidType
(
attrtype
),
attrtypmod
);
}
else
{
{
/* currently, we can't handle casting of expressions */
expr
=
size_target_expr
(
pstate
,
expr
,
attrtype
,
attrtypmod
);
elog
(
ERROR
,
"parser: attribute '%s' is of type '%s' but expression is of type '%s'"
,
colname
,
typeidTypeName
(
attrtype
),
typeidTypeName
(
type_id
));
}
}
}
}
...
@@ -514,7 +600,8 @@ make_targetlist_expr(ParseState *pstate,
...
@@ -514,7 +600,8 @@ make_targetlist_expr(ParseState *pstate,
tent
->
expr
=
expr
;
tent
->
expr
=
expr
;
return
tent
;
return
tent
;
}
}
/* make_targetlist_expr() */
/*
/*
* makeTargetNames -
* makeTargetNames -
...
...
src/backend/parser/parse_type.c
View file @
3ace5fd0
/*-------------------------------------------------------------------------
/*-------------------------------------------------------------------------
*
*
* parse_type.
h
* parse_type.
c
* handle type operations for parser
* handle type operations for parser
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.
8 1998/02/27 19:44:51 scrappy
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.
9 1998/05/09 23:29:54 thomas
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -15,11 +15,17 @@
...
@@ -15,11 +15,17 @@
#include "postgres.h"
#include "postgres.h"
#include "fmgr.h"
#include "fmgr.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
#include "nodes/primnodes.h"
#include "parser/parse_node.h"
#include "catalog/pg_type.h"
#include "catalog/pg_type.h"
#include "parser/parse_target.h"
#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "parser/parse_type.h"
#include "utils/syscache.h"
#include "utils/syscache.h"
/* check to see if a type id is valid,
/* check to see if a type id is valid,
* returns true if it is. By using this call before calling
* returns true if it is. By using this call before calling
* typeidType or typeidTypeName, more meaningful error messages
* typeidType or typeidTypeName, more meaningful error messages
...
...
src/include/parser/parse_coerce.h
0 → 100644
View file @
3ace5fd0
/*-------------------------------------------------------------------------
*
* parse_coerce.h
*
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: parse_coerce.h,v 1.1 1998/05/09 23:31:34 thomas Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef PARSE_COERCE_H
#define PARSE_COERCE_H
typedef
enum
CATEGORY
{
INVALID_TYPE
,
UNKNOWN_TYPE
,
BOOLEAN_TYPE
,
STRING_TYPE
,
NUMERIC_TYPE
,
DATETIME_TYPE
,
TIMESPAN_TYPE
,
GEOMETRIC_TYPE
,
USER_TYPE
,
MIXED_TYPE
}
CATEGORY
;
#define IS_BUILTIN_TYPE(t) \
(((t) == BOOLOID) \
|| ((t) == BPCHAROID) \
|| ((t) == VARCHAROID) \
|| ((t) == TEXTOID) \
|| ((t) == CASHOID) \
|| ((t) == INT4OID) \
|| ((t) == DATETIMEOID) \
|| ((t) == FLOAT8OID) \
|| ((t) == ABSTIMEOID) \
|| ((t) == TIMESTAMPOID) \
|| ((t) == RELTIMEOID))
/* IS_BINARY_COMPATIBLE()
* Check for types with the same underlying binary representation.
* This allows us to cheat and directly exchange values without
* going through the trouble of calling a conversion function.
*/
#define IS_BINARY_COMPATIBLE(a,b) \
(((a) == BPCHAROID && (b) == TEXTOID) \
|| ((a) == BPCHAROID && (b) == VARCHAROID) \
|| ((a) == VARCHAROID && (b) == TEXTOID) \
|| ((a) == VARCHAROID && (b) == BPCHAROID) \
|| ((a) == TEXTOID && (b) == BPCHAROID) \
|| ((a) == TEXTOID && (b) == VARCHAROID) \
|| ((a) == CASHOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == CASHOID) \
|| ((a) == DATETIMEOID && (b) == FLOAT8OID) \
|| ((a) == FLOAT8OID && (b) == DATETIMEOID) \
|| ((a) == ABSTIMEOID && (b) == TIMESTAMPOID) \
|| ((a) == TIMESTAMPOID && (b) == ABSTIMEOID) \
|| ((a) == ABSTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == ABSTIMEOID) \
|| ((a) == RELTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == RELTIMEOID))
/* IS_HIGHER_TYPE()
* These types are the most general in each of the type categories.
*/
#define IS_HIGHER_TYPE(t) \
(((t) == TEXTOID) \
|| ((t) == FLOAT8OID) \
|| ((t) == TIMESPANOID) \
|| ((t) == DATETIMEOID) \
|| ((t) == POLYGONOID))
/* IS_HIGHEST_TYPE()
* These types are the most general in each of the type categories.
* Since timespan and datetime overload so many functions, let's
* give datetime the preference.
* Since text is a generic string type let's leave it out too.
*/
#define IS_HIGHEST_TYPE(t) \
(((t) == FLOAT8OID) \
|| ((t) == DATETIMEOID) \
|| ((t) == TIMESPANOID))
extern
bool
IsPreferredType
(
CATEGORY
category
,
Oid
type
);
extern
Oid
PreferredType
(
CATEGORY
category
,
Oid
type
);
extern
CATEGORY
TypeCategory
(
Oid
type
);
extern
bool
can_coerce_type
(
int
nargs
,
Oid
*
input_typeids
,
Oid
*
func_typeids
);
extern
Node
*
coerce_type
(
ParseState
*
pstate
,
Node
*
node
,
Oid
inputTypeId
,
Oid
targetTypeId
);
#endif
/* PARSE_COERCE_H */
src/include/parser/parse_func.h
View file @
3ace5fd0
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: parse_func.h,v 1.
8 1998/02/26 04:42:45 momjian
Exp $
* $Id: parse_func.h,v 1.
9 1998/05/09 23:31:34 thomas
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -49,6 +49,6 @@ extern Node *
...
@@ -49,6 +49,6 @@ extern Node *
ParseFuncOrColumn
(
ParseState
*
pstate
,
char
*
funcname
,
List
*
fargs
,
ParseFuncOrColumn
(
ParseState
*
pstate
,
char
*
funcname
,
List
*
fargs
,
int
*
curr_resno
,
int
precedence
);
int
*
curr_resno
,
int
precedence
);
extern
void
func_error
(
char
*
caller
,
char
*
funcname
,
int
nargs
,
Oid
*
argtypes
);
extern
void
func_error
(
char
*
caller
,
char
*
funcname
,
int
nargs
,
Oid
*
argtypes
,
char
*
msg
);
#endif
/* PARSE_FUNC_H */
#endif
/* PARSE_FUNC_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment