Thread: PQexecParams and CURSOR

PQexecParams and CURSOR

From
"Laurent Marzullo"
Date:
Hello,

I Could not achieve to use CURSOR with PQexecParams ! How to you do ?

Here what I've done:
1)------------------------------------

paramValues[0] = "2";    // This is the parameter for the query

res = PQexec( conn , "DECLARE MY_CURSOR FOR "
                     "SELECT * FROM GRGL.RANGE_MODIFIER "
                     "WHERE WEAPON_ID = $1" );

=> ERROR
DECLARE failed: ERROR: There is no parameter 1






2)------------------------------------
then
paramValues[0] = "2";    // This is the parameter for the query

res = PQexecParams( conn ,
  "DECLARE MY_CURSOR FOR "
  "SELECT * FROM GRGL.RANGE_MODIFIER "
  "WHERE WEAPON_ID = $1",
  1,
  NULL,
  paramValues,
  NULL,
  NULL,
  0);

res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );

=> Error
FETCH failed: ERROR:  no value found for parameter 1



3)--------------------------------------
then
paramValues[0] = "2";    // This is the parameter for the query

res = PQexecParams( conn ,
  "DECLARE MY_CURSOR FOR "
  "SELECT * FROM GRGL.RANGE_MODIFIER "
  "WHERE WEAPON_ID = $1" ,
  1,
  NULL,
  paramValues,
  NULL,
  NULL,
  0);  );

res = PQexecParams( conn ,
  "FETCH 1 FROM MY_CURSOR",
  1,
  NULL,
  paramValues,
  NULL,
  NULL,
  0);

=> Error:
FETCH failed: ERROR:  bind message supplies 1 parameters, but prepared
statement "" requires 0


PLEASE, COULD YOU HELP ? THANKS.

Laurent Marzullo


Re: PQexecParams and CURSOR

From
Michael Fuhr
Date:
On Fri, Jan 14, 2005 at 12:31:24PM +0100, Laurent Marzullo wrote:

> paramValues[0] = "2";    // This is the parameter for the query
>
> res = PQexecParams( conn ,
>   "DECLARE MY_CURSOR FOR "
>   "SELECT * FROM GRGL.RANGE_MODIFIER "
>   "WHERE WEAPON_ID = $1",
>   1,
>   NULL,
>   paramValues,
>   NULL,
>   NULL,
>   0);

Are you checking the result status of this command?  If so, what
does your error checking code look like?  In 8.0.0rc5 this command
fails due to the missing keyword CURSOR before FOR.

> res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );
>
> => Error
> FETCH failed: ERROR:  no value found for parameter 1

Again, what does your error checking code look like?  If I correct
the syntax error in the DECLARE statement above then this query
succeeds.

> res = PQexecParams( conn ,
>   "FETCH 1 FROM MY_CURSOR",
>   1,
>   NULL,
>   paramValues,
>   NULL,
>   NULL,
>   0);
>
> => Error:
> FETCH failed: ERROR:  bind message supplies 1 parameters, but prepared
> statement "" requires 0

The error tells you what's wrong: you're supplying parameters that
the SQL statement isn't looking for.  Change the nParams value from
1 to 0 and pass NULL instead of paramValues, or use PQexec() instead
of PQexecParams() since you're not passing any parameters.

If you still have trouble then please post a minimal but complete
program so we can see everything you're doing.

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

Re: PQexecParams and CURSOR

From
"Laurent Marzullo"
Date:
Hello,

Ok so here is the full TEST program I try to run:
(It's a cut/paste + modification of program from PostgreSQL doc)

Thanks for any further help.
Laurent Marzullo

===================================================================
// vim:set ts=4 sts=4 sw=4 expandtab:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "libpq-fe.h"

static void
exit_nicely(PGconn *conn)
{
        PQfinish(conn);
        exit(1);
}

int
main(int argc, char **argv)
{
        const char *conninfo;
        PGconn     *conn;
        PGresult   *res;
        const char *paramValues[1];
        int                     i,
                                j;
        int                     i_fnum,
                                t_fnum,
                                b_fnum;

        if (argc > 1)
                conninfo = argv[1];
        else
                conninfo = "dbname = grgl";

        /* Make a connection to the database */
        conn = PQconnectdb(conninfo);

        /* Check to see that the backend connection was successfully made */
        if (PQstatus(conn) != CONNECTION_OK)
        {
                fprintf(stderr, "Connection to database '%s' failed.\n",
PQdb(conn));
                fprintf(stderr, "%s", PQerrorMessage(conn));
                exit_nicely(conn);
        }

        /* Here is our out-of-line parameter value */
        paramValues[0] = "2";

        PQexec( conn , "BEGIN" );
        res = PQexecParams(conn,
                "DECLARE my_cursor CURSOR FOR SELECT * FROM
grgl.range_modifier WHERE weapon_id = $1",
                1,
                NULL,
                paramValues,
                NULL,
                NULL,
                0);
        if (PQresultStatus(res) != PGRES_COMMAND_OK)
        {
                fprintf(stderr, "DECLARE failed: %s", PQerrorMessage(conn));
                PQclear(res);
                exit_nicely(conn);
        }
        //PQclear(res);

        // res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );
        /*
        res = PQexecParams(conn,
                "FETCH 1 FROM MY_CURSOR",
                0,
                NULL,
                NULL,
                NULL,
                NULL,
                0);
        */
        res = PQexecParams(conn,
                "FETCH 1 FROM MY_CURSOR",
                1,
                NULL,
                paramValues,
                NULL,
                NULL,
                0);
        if (PQresultStatus(res) != PGRES_TUPLES_OK)
        {
                fprintf(stderr, "FETCH failed: %s", PQerrorMessage(conn));
                PQclear(res);
                exit_nicely(conn);
        }

        /* Use PQfnumber to avoid assumptions about field order in result */
        i_fnum = PQfnumber(res, "weapon_id");
        t_fnum = PQfnumber(res, "lower_bound");
        b_fnum = PQfnumber(res, "upper_bound");

        for (i = 0; i < PQntuples(res); i++)
        {
                char       *iptr;
                char       *tptr;
                char       *bptr;
                int                     blen;
                uint64_t                ival;

                /* Get the field values (we ignore possibility they are
null!) */
                iptr = PQgetvalue(res, i, i_fnum);
                tptr = PQgetvalue(res, i, t_fnum);
                bptr = PQgetvalue(res, i, b_fnum);

                ival = strtoll(iptr , 0 , 10 );
                blen = PQgetlength(res, i, b_fnum);

                printf("tuple %d: got\n", i);
                printf(" i = (%d bytes) %d\n",
                           PQgetlength(res, i, i_fnum), ival);
                printf(" t = (%d bytes) '%s'\n",
                           PQgetlength(res, i, t_fnum), tptr);
                printf(" b = (%d bytes) '%s'\n",
                           PQgetlength(res, i, b_fnum), bptr);
                printf("\n\n");
        }

        PQclear(res);

        /* close the connection to the database and cleanup */
        PQfinish(conn);

        return 0;
}




-----Original Message-----
From: pgsql-general-owner@postgresql.org
[mailto:pgsql-general-owner@postgresql.org]On Behalf Of Michael Fuhr
Sent: Sunday, January 16, 2005 1:32 AM
To: Laurent Marzullo
Cc: pgsql-general@postgresql.org
Subject: Re: [GENERAL] PQexecParams and CURSOR


On Fri, Jan 14, 2005 at 12:31:24PM +0100, Laurent Marzullo wrote:

> paramValues[0] = "2";    // This is the parameter for the query
>
> res = PQexecParams( conn ,
>   "DECLARE MY_CURSOR FOR "
>   "SELECT * FROM GRGL.RANGE_MODIFIER "
>   "WHERE WEAPON_ID = $1",
>   1,
>   NULL,
>   paramValues,
>   NULL,
>   NULL,
>   0);

Are you checking the result status of this command?  If so, what
does your error checking code look like?  In 8.0.0rc5 this command
fails due to the missing keyword CURSOR before FOR.

> res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );
>
> => Error
> FETCH failed: ERROR:  no value found for parameter 1

Again, what does your error checking code look like?  If I correct
the syntax error in the DECLARE statement above then this query
succeeds.

> res = PQexecParams( conn ,
>   "FETCH 1 FROM MY_CURSOR",
>   1,
>   NULL,
>   paramValues,
>   NULL,
>   NULL,
>   0);
>
> => Error:
> FETCH failed: ERROR:  bind message supplies 1 parameters, but prepared
> statement "" requires 0

The error tells you what's wrong: you're supplying parameters that
the SQL statement isn't looking for.  Change the nParams value from
1 to 0 and pass NULL instead of paramValues, or use PQexec() instead
of PQexecParams() since you're not passing any parameters.

If you still have trouble then please post a minimal but complete
program so we can see everything you're doing.

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

---------------------------(end of broadcast)---------------------------
TIP 8: explain analyze is your friend


Re: PQexecParams and CURSOR

From
Michael Fuhr
Date:
On Mon, Jan 17, 2005 at 11:28:57AM +0100, Laurent Marzullo wrote:

>         // res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );

The above should work if you uncomment it and comment out or remove
the other two attempts to execute FETCH.

>         /*
>         res = PQexecParams(conn,
>                 "FETCH 1 FROM MY_CURSOR",
>                 0,
>                 NULL,
>                 NULL,
>                 NULL,
>                 NULL,
>                 0);
>         */

The above should also work if you uncomment it and comment out or
remove the other two.

>         res = PQexecParams(conn,
>                 "FETCH 1 FROM MY_CURSOR",
>                 1,
>                 NULL,
>                 paramValues,
>                 NULL,
>                 NULL,
>                 0);

This call fails because you're passing a parameter that the FETCH
statement doesn't need (you're passing 1 as the nParams argument
and the parameter list as paramValues).  Use one of the other two
methods, either PQexec() or PQexecParams() with nParams set to 0
and pass NULL instead of paramValues.

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

Re: PQexecParams and CURSOR

From
"Laurent Marzullo"
Date:

On Mon, Jan 17, 2005 at 11:28:57AM +0100, Laurent Marzullo wrote:

> >         // res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );

> The above should work if you uncomment it and comment out or remove
> the other two attempts to execute FETCH.

On my machine (2.6.7-gentoo-r9) and postgreSQL (postmaster --version) :
7.4.6

the command above gave:
FETCH failed: ERROR:  no value found for parameter 1

> >         /*
> >         res = PQexecParams(conn,
> >                 "FETCH 1 FROM MY_CURSOR",
> >                 0,
> >                 NULL,
> >                 NULL,
> >                 NULL,
> >                 NULL,
> >                 0);
> >         */

> The above should also work if you uncomment it and comment out or
> remove the other two.

This one alose gave the same result as the preceding one:

FETCH failed: ERROR:  no value found for parameter 1


My I install a version greater than 7.4.6 ?

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/


Re: PQexecParams and CURSOR

From
Tom Lane
Date:
"Laurent Marzullo" <laurent.marzullo@atosorigin.com> writes:
> Ok so here is the full TEST program I try to run:

I think you are running into an issue that was fixed during the 8.0
development cycle.  From the CVS logs:

2004-08-01 21:30  tgl

    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.

So what you are trying to do will work in 8.0 but not in 7.4.

            regards, tom lane

Re: PQexecParams and CURSOR

From
Michael Fuhr
Date:
On Mon, Jan 17, 2005 at 04:44:50PM +0100, Laurent Marzullo wrote:
> > >
> > >         // res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );
> >
> > The above should work if you uncomment it and comment out or remove
> > the other two attempts to execute FETCH.
>
> On my machine (2.6.7-gentoo-r9) and postgreSQL (postmaster --version) :
> 7.4.6
>
> the command above gave:
> FETCH failed: ERROR:  no value found for parameter 1

The problem appears to be in the 7.4.6 backend.  I did some tests
with 8.0.0rc5 and 7.4.6 and got the following results:

good    8.0.0rc5 backend, 8.0.0rc5 client
good    8.0.0rc5 backend, 7.4.6 client
bad    7.4.6 backend, 8.0.0rc5 client
bad    7.4.6 backend, 7.4.6 client

If I set log_error_verbosity to "verbose" then the 7.4.6 server
logs the following:

ERROR:  42704: no value found for parameter 1
LOCATION:  ExecEvalParam, execQual.c:518

I think the following message to pgsql-commiters announces the fix
that was applied to the development branch, which will soon be
released as 8.0.0:

http://archives.postgresql.org/pgsql-committers/2004-08/msg00028.php

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

Re: PQexecParams and CURSOR

From
"Laurent Marzullo"
Date:
ok.

Thanks all for you help.
I will take a look to 8.0

Laurent Marzullo

-----Original Message-----
From: pgsql-general-owner@postgresql.org
[mailto:pgsql-general-owner@postgresql.org]On Behalf Of Michael Fuhr
Sent: Monday, January 17, 2005 5:59 PM
To: Laurent Marzullo
Cc: pgsql-general@postgresql.org
Subject: Re: [GENERAL] PQexecParams and CURSOR


On Mon, Jan 17, 2005 at 04:44:50PM +0100, Laurent Marzullo wrote:
> > >
> > >         // res = PQexec( conn , "FETCH 1 FROM MY_CURSOR" );
> >
> > The above should work if you uncomment it and comment out or remove
> > the other two attempts to execute FETCH.
>
> On my machine (2.6.7-gentoo-r9) and postgreSQL (postmaster --version) :
> 7.4.6
>
> the command above gave:
> FETCH failed: ERROR:  no value found for parameter 1

The problem appears to be in the 7.4.6 backend.  I did some tests
with 8.0.0rc5 and 7.4.6 and got the following results:

good    8.0.0rc5 backend, 8.0.0rc5 client
good    8.0.0rc5 backend, 7.4.6 client
bad    7.4.6 backend, 8.0.0rc5 client
bad    7.4.6 backend, 7.4.6 client

If I set log_error_verbosity to "verbose" then the 7.4.6 server
logs the following:

ERROR:  42704: no value found for parameter 1
LOCATION:  ExecEvalParam, execQual.c:518

I think the following message to pgsql-commiters announces the fix
that was applied to the development branch, which will soon be
released as 8.0.0:

http://archives.postgresql.org/pgsql-committers/2004-08/msg00028.php

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)