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
d6429e55
Commit
d6429e55
authored
Mar 19, 2000
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Minor code rearrangement & doc improvement in eval_const_expressions().
parent
cf6420dd
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
129 additions
and
105 deletions
+129
-105
src/backend/optimizer/util/clauses.c
src/backend/optimizer/util/clauses.c
+129
-105
No files found.
src/backend/optimizer/util/clauses.c
View file @
d6429e55
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.6
1 2000/03/12 19:32:06
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.6
2 2000/03/19 18:20:38
tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
...
...
@@ -52,6 +52,7 @@ static bool check_subplans_for_ungrouped_vars_walker(Node *node,
check_subplans_for_ungrouped_vars_context
*
context
);
static
int
is_single_func
(
Node
*
node
);
static
Node
*
eval_const_expressions_mutator
(
Node
*
node
,
void
*
context
);
static
Expr
*
simplify_op_or_func
(
Expr
*
expr
,
List
*
args
);
Expr
*
...
...
@@ -918,108 +919,15 @@ eval_const_expressions_mutator (Node *node, void *context)
{
case
OP_EXPR
:
case
FUNC_EXPR
:
{
/*
* For an operator or function, we cannot simplify
* unless all the inputs are constants. (XXX possible
* future improvement: if the op/func is strict and
* at least one input is NULL, we could simplify to NULL.
* But we do not currently have any way to know if the
* op/func is strict or not. For now, a NULL input is
* treated the same as any other constant node.)
*/
bool
args_all_const
=
true
;
List
*
arg
;
Oid
funcid
;
Oid
result_typeid
;
HeapTuple
func_tuple
;
Form_pg_proc
funcform
;
Type
resultType
;
Datum
const_val
;
bool
const_is_null
;
bool
isDone
;
foreach
(
arg
,
args
)
{
if
(
!
IsA
(
lfirst
(
arg
),
Const
))
{
args_all_const
=
false
;
break
;
}
}
if
(
!
args_all_const
)
break
;
/*
* Get the function procedure's OID and look to see
* whether it is marked proiscachable.
* Code for op/func case is pretty bulky, so split it out
* as a separate function.
*/
if
(
expr
->
opType
==
OP_EXPR
)
{
Oper
*
oper
=
(
Oper
*
)
expr
->
oper
;
replace_opid
(
oper
);
funcid
=
oper
->
opid
;
result_typeid
=
oper
->
opresulttype
;
}
else
{
Func
*
func
=
(
Func
*
)
expr
->
oper
;
funcid
=
func
->
funcid
;
result_typeid
=
func
->
functype
;
}
/* Someday lsyscache.c might provide a function for this */
func_tuple
=
SearchSysCacheTuple
(
PROCOID
,
ObjectIdGetDatum
(
funcid
),
0
,
0
,
0
);
if
(
!
HeapTupleIsValid
(
func_tuple
))
elog
(
ERROR
,
"Function OID %u does not exist"
,
funcid
);
funcform
=
(
Form_pg_proc
)
GETSTRUCT
(
func_tuple
);
if
(
!
funcform
->
proiscachable
)
break
;
/*
* Also check to make sure it doesn't return a set.
*
* XXX would it be better to take the result type from the
* pg_proc tuple, rather than the Oper or Func node?
*/
if
(
funcform
->
proretset
)
newexpr
=
simplify_op_or_func
(
expr
,
args
);
if
(
newexpr
)
/* successfully simplified it */
return
(
Node
*
)
newexpr
;
/* else fall out to build new Expr node with simplified args */
break
;
/*
* OK, looks like we can simplify this operator/function.
* We use the executor's routine ExecEvalExpr() to avoid
* duplication of code and ensure we get the same result
* as the executor would get.
*
* Build a new Expr node containing the already-simplified
* arguments. The only other setup needed here is the
* replace_opid() that we already did for the OP_EXPR case.
*/
newexpr
=
makeNode
(
Expr
);
newexpr
->
typeOid
=
expr
->
typeOid
;
newexpr
->
opType
=
expr
->
opType
;
newexpr
->
oper
=
expr
->
oper
;
newexpr
->
args
=
args
;
/*
* It is OK to pass econtext = NULL because none of the
* ExecEvalExpr() code used in this situation will use
* econtext. That might seem fortuitous, but it's not
* so unreasonable --- a constant expression does not
* depend on context, by definition, n'est ce pas?
*/
const_val
=
ExecEvalExpr
((
Node
*
)
newexpr
,
NULL
,
&
const_is_null
,
&
isDone
);
Assert
(
isDone
);
/* if this isn't set, we blew it... */
pfree
(
newexpr
);
/*
* Make the constant result node.
*/
resultType
=
typeidType
(
result_typeid
);
return
(
Node
*
)
makeConst
(
result_typeid
,
typeLen
(
resultType
),
const_val
,
const_is_null
,
typeByVal
(
resultType
),
false
,
false
);
}
case
OR_EXPR
:
{
/*
...
...
@@ -1163,10 +1071,7 @@ eval_const_expressions_mutator (Node *node, void *context)
/*
* If we can simplify the input to a constant, then we don't need
* the RelabelType node anymore: just change the type field of
* the Const node. Otherwise keep the RelabelType node.
*
* XXX if relabel has a nondefault resulttypmod, do we need to
* keep it to show that? At present I don't think so.
* the Const node. Otherwise, copy the RelabelType node.
*/
RelabelType
*
relabel
=
(
RelabelType
*
)
node
;
Node
*
arg
;
...
...
@@ -1177,6 +1082,11 @@ eval_const_expressions_mutator (Node *node, void *context)
Const
*
con
=
(
Const
*
)
arg
;
con
->
consttype
=
relabel
->
resulttype
;
/*
* relabel's resulttypmod is discarded, which is OK for now;
* if the type actually needs a runtime length coercion then
* there should be a function call to do it just above this node.
*/
return
(
Node
*
)
con
;
}
else
...
...
@@ -1296,6 +1206,120 @@ eval_const_expressions_mutator (Node *node, void *context)
(
void
*
)
context
);
}
/*
* Subroutine for eval_const_expressions: try to evaluate an op or func
*
* Inputs are the op or func Expr node, and the pre-simplified argument list.
* Returns a simplified expression if successful, or NULL if cannot
* simplify the op/func.
*
* XXX Possible future improvement: if the func is SQL-language, and its
* definition is simply "SELECT expression", we could parse and substitute
* the expression here. This would avoid much runtime overhead, and perhaps
* expose opportunities for constant-folding within the expression even if
* not all the func's input args are constants. It'd be appropriate to do
* here, and not in the parser, since we wouldn't want it to happen until
* after rule substitution/rewriting.
*/
static
Expr
*
simplify_op_or_func
(
Expr
*
expr
,
List
*
args
)
{
List
*
arg
;
Oid
funcid
;
Oid
result_typeid
;
HeapTuple
func_tuple
;
Form_pg_proc
funcform
;
Type
resultType
;
Expr
*
newexpr
;
Datum
const_val
;
bool
const_is_null
;
bool
isDone
;
/*
* For an operator or function, we cannot simplify unless all the inputs
* are constants. (XXX possible future improvement: if the op/func is
* strict and at least one input is NULL, we could simplify to NULL.
* But we do not currently have any way to know if the op/func is strict
* or not. For now, a NULL input is treated the same as any other
* constant node.)
*/
foreach
(
arg
,
args
)
{
if
(
!
IsA
(
lfirst
(
arg
),
Const
))
return
NULL
;
}
/*
* Get the function procedure's OID and look to see
* whether it is marked proiscachable.
*/
if
(
expr
->
opType
==
OP_EXPR
)
{
Oper
*
oper
=
(
Oper
*
)
expr
->
oper
;
replace_opid
(
oper
);
/* OK to scribble on input to this extent */
funcid
=
oper
->
opid
;
result_typeid
=
oper
->
opresulttype
;
}
else
{
Func
*
func
=
(
Func
*
)
expr
->
oper
;
funcid
=
func
->
funcid
;
result_typeid
=
func
->
functype
;
}
/* Someday lsyscache.c might provide a function for this */
func_tuple
=
SearchSysCacheTuple
(
PROCOID
,
ObjectIdGetDatum
(
funcid
),
0
,
0
,
0
);
if
(
!
HeapTupleIsValid
(
func_tuple
))
elog
(
ERROR
,
"Function OID %u does not exist"
,
funcid
);
funcform
=
(
Form_pg_proc
)
GETSTRUCT
(
func_tuple
);
if
(
!
funcform
->
proiscachable
)
return
NULL
;
/*
* Also check to make sure it doesn't return a set.
*/
if
(
funcform
->
proretset
)
return
NULL
;
/*
* OK, looks like we can simplify this operator/function.
*
* We use the executor's routine ExecEvalExpr() to avoid duplication of
* code and ensure we get the same result as the executor would get.
*
* Build a new Expr node containing the already-simplified arguments.
* The only other setup needed here is the replace_opid() that we already
* did for the OP_EXPR case.
*/
newexpr
=
makeNode
(
Expr
);
newexpr
->
typeOid
=
expr
->
typeOid
;
newexpr
->
opType
=
expr
->
opType
;
newexpr
->
oper
=
expr
->
oper
;
newexpr
->
args
=
args
;
/*
* It is OK to pass econtext = NULL because none of the ExecEvalExpr()
* code used in this situation will use econtext. That might seem
* fortuitous, but it's not so unreasonable --- a constant expression does
* not depend on context, by definition, n'est ce pas?
*/
const_val
=
ExecEvalExpr
((
Node
*
)
newexpr
,
NULL
,
&
const_is_null
,
&
isDone
);
Assert
(
isDone
);
/* if this isn't set, we blew it... */
pfree
(
newexpr
);
/*
* Make the constant result node.
*
* XXX would it be better to take the result type from the
* pg_proc tuple, rather than the Oper or Func node?
*/
resultType
=
typeidType
(
result_typeid
);
return
(
Expr
*
)
makeConst
(
result_typeid
,
typeLen
(
resultType
),
const_val
,
const_is_null
,
typeByVal
(
resultType
),
false
,
false
);
}
/*
* Standard expression-tree walking support
*
...
...
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