8000 Allow DECLARE CURSOR to take parameters from the portal in which it is · postgrespro/postgres@f622c54 · GitHub
[go: up one dir, main page]

Skip to content

Commit f622c54

Browse files
committed
Allow DECLARE CURSOR to take parameters from the portal in which it is
executed. Previously, the DECLARE would succeed but subsequent FETCHes would fail since the parameter values supplied to DECLARE were not propagated to the portal created for the cursor. In support of this, add type Oids to ParamListInfo entries, which seems like a good idea anyway since code that extracts a value can double-check that it got the type of value it was expecting. Oliver Jowett, with minor editorialization by Tom Lane.
1 parent 410b1df commit f622c54

File tree

18 files changed

+263
-115
lines changed
  • optimizer/util
  • tcop
  • include
  • pl/plpgsql/src
  • test/regress
  • 18 files changed

    +263
    -115
    lines changed

    src/backend/commands/portalcmds.c

    Lines changed: 15 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -14,7 +14,7 @@
    1414
    *
    1515
    *
    1616
    * IDENTIFICATION
    17-
    * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.30 2004/07/31 00:45:31 tgl Exp $
    17+
    * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.31 2004/08/02 01:30:40 tgl Exp $
    1818
    *
    1919
    *-------------------------------------------------------------------------
    2020
    */
    @@ -36,7 +36,7 @@
    3636
    * Execute SQL DECLARE CURSOR command.
    3737
    */
    3838
    void
    39-
    PerformCursorOpen(DeclareCursorStmt *stmt)
    39+
    PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
    4040
    {
    4141
    List *rewritten;
    4242
    Query *query;
    @@ -104,6 +104,17 @@ PerformCursorOpen(DeclareCursorStmt *stmt)
    104104
    list_make1(plan),
    105105
    PortalGetHeapMemory(portal));
    106106

    107+
    /*
    108+
    * Also copy the outer portal's parameter list into the inner portal's
    109+
    * memory context. We want to pass down the parameter values in case
    110+
    * we had a command like
    111+
    * DECLARE c CURSOR FOR SELECT ... WHERE foo = $1
    112+
    * This will have been parsed using the outer parameter set and the
    113+
    * parameter value needs to be preserved for use when the cursor is
    114+
    * executed.
    115+
    */
    116+
    params = copyParamList(params);
    117+
    107118
    MemoryContextSwitchTo(oldContext);
    108119

    109120
    /*
    @@ -123,9 +134,9 @@ PerformCursorOpen(DeclareCursorStmt *stmt)
    123134
    }
    124135

    125136
    /*
    126-
    * Start execution --- never any params for a cursor.
    137+
    * Start execution, inserting parameters if any.
    127138
    */
    128-
    PortalStart(portal, NULL);
    139+
    PortalStart(portal, params);
    129140

    130141
    Assert(portal->strategy == PORTAL_ONE_SELECT);
    131142

    src/backend/commands/prepare.c

    Lines changed: 6 additions & 5 deletions
    Original file line numberDiff line numberDiff line change
    @@ -10,7 +10,7 @@
    1010
    * Copyright (c) 2002-2003, PostgreSQL Global Development Group
    1111
    *
    1212
    * IDENTIFICATION
    13-
    * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.28 2004/06/11 01:08:38 tgl Exp $
    13+
    * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.29 2004/08/02 01:30:40 tgl Exp $
    1414
    *
    1515
    *-------------------------------------------------------------------------
    1616
    */
    @@ -200,7 +200,7 @@ ExecuteQuery(ExecuteStmt *stmt, DestReceiver *dest, char *completionTag)
    200200

    201201
    /*
    202202
    * Evaluates a list of parameters, using the given executor state. It
    203-
    * requires a list of the parameter values themselves, and a list of
    203+
    * requires a list of the parameter expressions themselves, and a list of
    204204
    * their types. It returns a filled-in ParamListInfo -- this can later
    205205
    * be passed to CreateQueryDesc(), which allows the executor to make use
    206206
    * of the parameters during query execution.
    @@ -211,7 +211,7 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
    211211
    int nargs = list_length(argtypes);
    212212
    ParamListInfo paramLI;
    213213
    List *exprstates;
    214-
    ListCell *l;
    214+
    ListCell *le, *la;
    215215
    int i = 0;
    216216

    217217
    /* Parser should have caught this error, but check for safety */
    @@ -223,9 +223,9 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
    223223
    paramLI = (ParamListInfo)
    224224
    palloc0((nargs + 1) * sizeof(ParamListInfoData));
    225225

    226-
    foreach(l, exprstates)
    226+
    forboth(le, exprstates, la, argtypes)
    227227
    {
    228-
    ExprState *n = lfirst(l);
    228+
    ExprState *n = lfirst(le);
    229229
    bool isNull;
    230230

    231231
    paramLI[i].value = ExecEvalExprSwitchContext(n,
    @@ -234,6 +234,7 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
    234234
    NULL);
    235235
    paramLI[i].kind = PARAM_NUM;
    236236
    paramLI[i].id = i + 1;
    237+
    paramLI[i].ptype = lfirst_oid(la);
    237238
    paramLI[i].isnull = isNull;
    238239

    239240
    i++;

    src/backend/commands/schemacmds.c

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -8,7 +8,7 @@
    88
    *
    99
    *
    1010
    * IDENTIFICATION
    11-
    * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.21 2004/08/01 20:30:48 tgl Exp $
    11+
    * $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.22 2004/08/02 01:30:40 tgl Exp $
    1212
    *
    1313
    *-------------------------------------------------------------------------
    1414
    */
    @@ -168,7 +168,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
    168168
    /* schemas should contain only utility stmts */
    169169
    Assert(querytree->commandType == CMD_UTILITY);
    170170
    /* do this step */
    171-
    ProcessUtility(querytree->utilityStmt, None_Receiver, NULL);
    171+
    ProcessUtility(querytree->utilityStmt, NULL, None_Receiver, NULL);
    172172
    /* make sure later steps can see the object created here */
    173173
    CommandCounterIncrement();
    174174
    }

    src/backend/executor/execQual.c

    Lines changed: 12 additions & 50 deletions
    Original file line numberDiff line numberDiff line change
    @@ -8,7 +8,7 @@
    88
    *
    99
    *
    1010
    * IDENTIFICATION
    11-
    * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.164 2004/06/09 19:08:14 tgl Exp $
    11+
    * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.165 2004/08/02 01:30:41 tgl Exp $
    1212
    *
    1313
    *-------------------------------------------------------------------------
    1414
    */
    @@ -589,56 +589,18 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
    589589
    else
    590590
    {
    591591
    /*
    592-
    * All other parameter types must be sought in
    593-
    * ecxt_param_list_info. NOTE: The last entry in the param array
    594-
    * is always an entry with kind == PARAM_INVALID.
    592+
    * All other parameter types must be sought in ecxt_param_list_info.
    595593
    */
    596-
    ParamListInfo paramList = econtext->ecxt_param_list_info;
    597-
    char *thisParamName = expression->paramname;
    598-
    bool matchFound = false;
    599-
    600-
    if (paramList != NULL)
    601-
    {
    602-
    while (paramList->kind != PARAM_INVALID && !matchFound)
    603-
    {
    604-
    if (thisParamKind == paramList->kind)
    605-
    {
    606-
    switch (thisParamKind)
    607-
    {
    608-
    case PARAM_NAMED:
    609-
    if (strcmp(paramList->name, thisParamName) == 0)
    610-
    matchFound = true;
    611-
    break;
    612-
    case PARAM_NUM:
    613-
    if (paramList->id == thisParamId)
    614-
    matchFound = true;
    615-
    break;
    616-
    default:
    617-
    elog(ERROR, "unrecognized paramkind: %d",
    618-
    thisParamKind);
    619-
    }
    620-
    }
    621-
    if (!matchFound)
    622-
    paramList++;
    623-
    } /* while */
    624-
    } /* if */
    625-
    626-
    if (!matchFound)
    627-
    {
    628-
    if (thisParamKind == PARAM_NAMED)
    629-
    ereport(ERROR,
    630-
    (errcode(ERRCODE_UNDEFINED_OBJECT),
    631-
    errmsg("no value found for parameter \"%s\"",
    632-
    thisParamName)));
    633-
    else
    634-
    ereport(ERROR,
    635-
    (errcode(ERRCODE_UNDEFINED_OBJECT),
    636-
    errmsg("no value found for parameter %d",
    637-
    thisParamId)));
    638-
    }
    639-
    640-
    *isNull = paramList->isnull;
    641-
    return paramList->value;
    594+
    ParamListInfo paramInfo;
    595+
    596+
    paramInfo = lookupParam(econtext->ecxt_param_list_info,
    597+
    thisParamKind,
    598+
    expression->paramname,
    599+
    thisParamId,
    600+
    false);
    601+
    Assert(paramInfo->ptype == expression->paramtype);
    602+
    *isNull = paramInfo->isnull;
    603+
    return paramInfo->value;
    642604
    }
    643605
    }
    644606

    src/backend/executor/functions.c

    Lines changed: 6 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -8,7 +8,7 @@
    88
    *
    99
    *
    1010
    * IDENTIFICATION
    11-
    * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.83 2004/07/15 13:51:38 tgl Exp $
    11+
    * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.84 2004/08/02 01:30:41 tgl Exp $
    1212
    *
    1313
    *-------------------------------------------------------------------------
    1414
    */
    @@ -58,6 +58,7 @@ typedef struct local_es
    5858
    */
    5959
    typedef struct
    6060
    {
    61+
    Oid *argtypes; /* resolved types of arguments */
    6162
    Oid rettype; /* actual return type */
    6263
    int typlen; /* length of the return type */
    6364
    bool typbyval; /* true if return type is pass by value */
    @@ -223,6 +224,7 @@ init_sql_fcache(FmgrInfo *finfo)
    223224
    }
    224225
    else
    225226
    argOidVect = NULL;
    227+
    fcache->argtypes = argOidVect;
    226228

    227229
    tmp = SysCacheGetAttr(PROCOID,
    228230
    procedureTuple,
    @@ -283,7 +285,8 @@ postquel_getnext(execution_state *es)
    283285

    284286
    if (es->qd->operation == CMD_UTILITY)
    285287
    {
    286-
    ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->dest, NULL);
    288+
    ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->params,
    289+
    es->qd->dest, NULL);
    287290
    return NULL;
    288291
    }
    289292

    @@ -332,6 +335,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
    332335
    {
    333336
    paramLI[i].kind = PARAM_NUM;
    334337
    paramLI[i].id = i + 1;
    338+
    paramLI[i].ptype = fcache->argtypes[i];
    335339
    paramLI[i].value = fcinfo->arg[i];
    336340
    paramLI[i].isnull = fcinfo->argnull[i];
    337341
    }

    src/backend/executor/spi.c

    Lines changed: 5 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -8,7 +8,7 @@
    88
    *
    99
    *
    1010
    * IDENTIFICATION
    11-
    * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.122 2004/07/31 20:55:41 tgl Exp $
    11+
    * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.123 2004/08/02 01:30:41 tgl Exp $
    1212
    *
    1313
    *-------------------------------------------------------------------------
    1414
    */
    @@ -820,6 +820,7 @@ SPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls)
    820820
    {
    821821
    paramLI[k].kind = PARAM_NUM;
    822822
    paramLI[k].id = k + 1;
    823+
    paramLI[k].ptype = spiplan->argtypes[k];
    823824
    paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
    824825
    if (paramLI[k].isnull)
    825826
    {
    @@ -1251,7 +1252,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
    12511252
    res = SPI_OK_UTILITY;
    12521253
    if (plan == NULL)
    12531254
    {
    1254-
    ProcessUtility(queryTree->utilityStmt, dest, NULL);
    1255+
    ProcessUtility(queryTree->utilityStmt, NULL, dest, NULL);
    12551256
    CommandCounterIncrement();
    12561257
    }
    12571258
    }
    @@ -1319,6 +1320,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
    13191320
    {
    13201321
    paramLI[k].kind = PARAM_NUM;
    13211322
    paramLI[k].id = k + 1;
    1323+
    paramLI[k].ptype = plan->argtypes[k];
    13221324
    paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
    13231325
    paramLI[k].value = Values[k];
    13241326
    }
    @@ -1366,7 +1368,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
    13661368
    dest = CreateDestReceiver(queryTree->canSetTag ? SPI : None, NULL);
    13671369
    if (queryTree->commandType == CMD_UTILITY)
    13681370
    {
    1369-
    ProcessUtility(queryTree->utilityStmt, dest, NULL);
    1371+
    ProcessUtility(queryTree->utilityStmt, paramLI, dest, NULL);
    13701372
    res = SPI_OK_UTILITY;
    13711373
    CommandCounterIncrement();
    13721374
    }

    src/backend/nodes/Makefile

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -4,7 +4,7 @@
    44
    # Makefile for backend/nodes
    55
    #
    66
    # IDENTIFICATION
    7-
    # $PostgreSQL: pgsql/src/backend/nodes/Makefile,v 1.16 2004/01/07 18:43:36 neilc Exp $
    7+
    # $PostgreSQL: pgsql/src/backend/nodes/Makefile,v 1.17 2004/08/02 01:30:42 tgl Exp $
    88
    #
    99
    #-------------------------------------------------------------------------
    1010

    @@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
    1414

    1515
    OBJS = nodeFuncs.o nodes.o list.o bitmapset.o \
    1616
    copyfuncs.o equalfuncs.o makefuncs.o \
    17-
    outfuncs.o readfuncs.o print.o read.o value.o
    17+
    outfuncs.o readfuncs.o print.o read.o params.o value.o
    1818

    1919
    all: SUBSYS.o
    2020

    0 commit comments

    Comments
     (0)
    0