Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 76b6aa4

Browse files
committed
Support parameters in CALL
To support parameters in CALL, move the parse analysis of the procedure and arguments into the global transformation phase, so that the parser hooks can be applied. And then at execution time pass the parameters from ProcessUtility on to ExecuteCallStmt.
1 parent a6a8013 commit 76b6aa4

File tree

11 files changed

+124
-24
lines changed

11 files changed

+124
-24
lines changed

src/backend/commands/functioncmds.c

+4-21
Original file line numberDiff line numberDiff line change
@@ -2212,11 +2212,9 @@ ExecuteDoStmt(DoStmt *stmt, bool atomic)
22122212
* commits that might occur inside the procedure.
22132213
*/
22142214
void
2215-
ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
2215+
ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic)
22162216
{
2217-
List *targs;
22182217
ListCell *lc;
2219-
Node *node;
22202218
FuncExpr *fexpr;
22212219
int nargs;
22222220
int i;
@@ -2228,24 +2226,8 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22282226
ExprContext *econtext;
22292227
HeapTuple tp;
22302228

2231-
/* We need to do parse analysis on the procedure call and its arguments */
2232-
targs = NIL;
2233-
foreach(lc, stmt->funccall->args)
2234-
{
2235-
targs = lappend(targs, transformExpr(pstate,
2236-
(Node *) lfirst(lc),
2237-
EXPR_KIND_CALL_ARGUMENT));
2238-
}
2239-
2240-
node = ParseFuncOrColumn(pstate,
2241-
stmt->funccall->funcname,
2242-
targs,
2243-
pstate->p_last_srf,
2244-
stmt->funccall,
2245-
true,
2246-
stmt->funccall->location);
2247-
2248-
fexpr = castNode(FuncExpr, node);
2229+
fexpr = stmt->funcexpr;
2230+
Assert(fexpr);
22492231

22502232
aclresult = pg_proc_aclcheck(fexpr->funcid, GetUserId(), ACL_EXECUTE);
22512233
if (aclresult != ACLCHECK_OK)
@@ -2289,6 +2271,7 @@ ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic)
22892271
* we can't free this context till the procedure returns.
22902272
*/
22912273
estate = CreateExecutorState();
2274+
estate->es_param_list_info = params;
22922275
econtext = CreateExprContext(estate);
22932276

22942277
i = 0;

src/backend/nodes/copyfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -3231,6 +3231,7 @@ _copyCallStmt(const CallStmt *from)
32313231
CallStmt *newnode = makeNode(CallStmt);
32323232

32333233
COPY_NODE_FIELD(funccall);
3234+
COPY_NODE_FIELD(funcexpr);
32343235

32353236
return newnode;
32363237
}

src/backend/nodes/equalfuncs.c

+1
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,7 @@ static bool
12061206
_equalCallStmt(const CallStmt *a, const CallStmt *b)
12071207
{
12081208
COMPARE_NODE_FIELD(funccall);
1209+
COMPARE_NODE_FIELD(funcexpr);
12091210

12101211
return true;
12111212
}

src/backend/parser/analyze.c

+45
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
#include "parser/parse_coerce.h"
3737
#include "parser/parse_collate.h"
3838
#include "parser/parse_cte.h"
39+
#include "parser/parse_expr.h"
40+
#include "parser/parse_func.h"
3941
#include "parser/parse_oper.h"
4042
#include "parser/parse_param.h"
4143
#include "parser/parse_relation.h"
@@ -74,6 +76,8 @@ static Query *transformExplainStmt(ParseState *pstate,
7476
ExplainStmt *stmt);
7577
static Query *transformCreateTableAsStmt(ParseState *pstate,
7678
CreateTableAsStmt *stmt);
79+
static Query *transformCallStmt(ParseState *pstate,
80+
CallStmt *stmt);
7781
static void transformLockingClause(ParseState *pstate, Query *qry,
7882
LockingClause *lc, bool pushedDown);
7983
#ifdef RAW_EXPRESSION_COVERAGE_TEST
@@ -318,6 +322,10 @@ transformStmt(ParseState *pstate, Node *parseTree)
318322
(CreateTableAsStmt *) parseTree);
319323
break;
320324

325+
case T_CallStmt:
326+
result = transformCallStmt(pstate,
327+
(CallStmt *) parseTree);
328+
321329
default:
322330

323331
/*
@@ -2571,6 +2579,43 @@ transformCreateTableAsStmt(ParseState *pstate, CreateTableAsStmt *stmt)
25712579
return result;
25722580
}
25732581

2582+
/*
2583+
* transform a CallStmt
2584+
*
2585+
* We need to do parse analysis on the procedure call and its arguments.
2586+
*/
2587+
static Query *
2588+
transformCallStmt(ParseState *pstate, CallStmt *stmt)
2589+
{
2590+
List *targs;
2591+
ListCell *lc;
2592+
Node *node;
2593+
Query *result;
2594+
2595+
targs = NIL;
2596+
foreach(lc, stmt->funccall->args)
2597+
{
2598+
targs = lappend(targs, transformExpr(pstate,
2599+
(Node *) lfirst(lc),
2600+
EXPR_KIND_CALL_ARGUMENT));
2601+
}
2602+
2603+
node = ParseFuncOrColumn(pstate,
2604+
stmt->funccall->funcname,
2605+
targs,
2606+
pstate->p_last_srf,
2607+
stmt->funccall,
2608+
true,
2609+
stmt->funccall->location);
2610+
2611+
stmt->funcexpr = castNode(FuncExpr, node);
2612+
2613+
result = makeNode(Query);
2614+
result->commandType = CMD_UTILITY;
2615+
result->utilityStmt = (Node *) stmt;
2616+
2617+
return result;
2618+
}
25742619

25752620
/*
25762621
* Produce a string representation of a LockClauseStrength value.

src/backend/tcop/utility.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ standard_ProcessUtility(PlannedStmt *pstmt,
660660
break;
661661

662662
case T_CallStmt:
663-
ExecuteCallStmt(pstate, castNode(CallStmt, parsetree),
663+
ExecuteCallStmt(castNode(CallStmt, parsetree), params,
664664
(context != PROCESS_UTILITY_TOPLEVEL || IsTransactionBlock()));
665665
break;
666666

src/include/commands/defrem.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define DEFREM_H
1616

1717
#include "catalog/objectaddress.h"
18+
#include "nodes/params.h"
1819
#include "nodes/parsenodes.h"
1920
#include "utils/array.h"
2021

@@ -61,7 +62,7 @@ extern void DropTransformById(Oid transformOid);
6162
extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
6263
oidvector *proargtypes, Oid nspOid);
6364
extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
64-
extern void ExecuteCallStmt(ParseState *pstate, CallStmt *stmt, bool atomic);
65+
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic);
6566
extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
6667
extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
6768
extern void interpret_function_parameter_list(ParseState *pstate,

src/include/nodes/parsenodes.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -2814,7 +2814,8 @@ typedef struct InlineCodeBlock
28142814
typedef struct CallStmt
28152815
{
28162816
NodeTag type;
2817-
FuncCall *funccall;
2817+
FuncCall *funccall; /* from the parser */
2818+
FuncExpr *funcexpr; /* transformed */
28182819
} CallStmt;
28192820

28202821
typedef struct CallContext

src/pl/plpgsql/src/expected/plpgsql_call.out

+19
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,26 @@ SELECT * FROM test1;
3535
55
3636
(1 row)
3737

38+
-- nested CALL
39+
TRUNCATE TABLE test1;
40+
CREATE PROCEDURE test_proc4(y int)
41+
LANGUAGE plpgsql
42+
AS $$
43+
BEGIN
44+
CALL test_proc3(y);
45+
CALL test_proc3($1);
46+
END;
47+
$$;
48+
CALL test_proc4(66);
49+
SELECT * FROM test1;
50+
a
51+
----
52+
66
53+
66
54+
(2 rows)
55+
3856
DROP PROCEDURE test_proc1;
3957
DROP PROCEDURE test_proc2;
4058
DROP PROCEDURE test_proc3;
59+
DROP PROCEDURE test_proc4;
4160
DROP TABLE test1;

src/pl/plpgsql/src/sql/plpgsql_call.sql

+18
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,26 @@ CALL test_proc3(55);
4040
SELECT * FROM test1;
4141

4242

43+
-- nested CALL
44+
TRUNCATE TABLE test1;
45+
46+
CREATE PROCEDURE test_proc4(y int)
47+
LANGUAGE plpgsql
48+
AS $$
49+
BEGIN
50+
CALL test_proc3(y);
51+
CALL test_proc3($1);
52+
END;
53+
$$;
54+
55+
CALL test_proc4(66);
56+
57+
SELECT * FROM test1;
58+
59+
4360
DROP PROCEDURE test_proc1;
4461
DROP PROCEDURE test_proc2;
4562
DROP PROCEDURE test_proc3;
63+
DROP PROCEDURE test_proc4;
4664

4765
DROP TABLE test1;

src/test/regress/expected/create_procedure.out

+16
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ AS $$
5555
SELECT 5;
5656
$$;
5757
CALL ptest2();
58+
-- nested CALL
59+
TRUNCATE cp_test;
60+
CREATE PROCEDURE ptest3(y text)
61+
LANGUAGE SQL
62+
AS $$
63+
CALL ptest1(y);
64+
CALL ptest1($1);
65+
$$;
66+
CALL ptest3('b');
67+
SELECT * FROM cp_test;
68+
a | b
69+
---+---
70+
1 | b
71+
1 | b
72+
(2 rows)
73+
5874
-- various error cases
5975
CALL version(); -- error: not a procedure
6076
ERROR: version() is not a procedure

src/test/regress/sql/create_procedure.sql

+15
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ $$;
3131
CALL ptest2();
3232

3333

34+
-- nested CALL
35+
TRUNCATE cp_test;
36+
37+
CREATE PROCEDURE ptest3(y text)
38+
LANGUAGE SQL
39+
AS $$
40+
CALL ptest1(y);
41+
CALL ptest1($1);
42+
$$;
43+
44+
CALL ptest3('b');
45+
46+
SELECT * FROM cp_test;
47+
48+
3449
-- various error cases
3550

3651
CALL version(); -- error: not a procedure

0 commit comments

Comments
 (0)