1.13. Example Programs

Example 1-1. libpq Example Program 1

    /*
     * testlibpq.c
     *
     * Test the C version of libpq, the PostgreSQL frontend
     * library.
     */
    #include <stdio.h>
    #include <libpq-fe.h>
    
    void
    exit_nicely(PGconn *conn)
    {
        PQfinish(conn);
        exit(1);
    }
    
    main()
    {
        char       *pghost,
                   *pgport,
                   *pgoptions,
                   *pgtty;
        char       *dbName;
        int         nFields;
        int         i,
                    j;
    
        /* FILE *debug; */
    
        PGconn     *conn;
        PGresult   *res;
    
        /*
         * begin, by setting the parameters for a backend connection if the
         * parameters are null, then the system will try to use reasonable
         * defaults by looking up environment variables or, failing that,
         * using hardwired constants
         */
        pghost = NULL;              /* host name of the backend server */
        pgport = NULL;              /* port of the backend server */
        pgoptions = NULL;           /* special options to start up the backend
                                     * server */
        pgtty = NULL;               /* debugging tty for the backend server */
        dbName = "template1";
    
        /* make a connection to the database */
        conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
    
        /*
         * check to see that the backend connection was successfully made
         */
        if (PQstatus(conn) == CONNECTION_BAD)
        {
            fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
            fprintf(stderr, "%s", PQerrorMessage(conn));
            exit_nicely(conn);
        }
    
        /* debug = fopen("/tmp/trace.out","w"); */
        /* PQtrace(conn, debug);  */
    
        /* start a transaction block */
        res = PQexec(conn, "BEGIN");
        if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            fprintf(stderr, "BEGIN command failed\n");
            PQclear(res);
            exit_nicely(conn);
        }
    
        /*
         * should PQclear PGresult whenever it is no longer needed to avoid
         * memory leaks
         */
        PQclear(res);
    
        /*
         * fetch rows from the pg_database, the system catalog of
         * databases
         */
        res = PQexec(conn, "DECLARE mycursor CURSOR FOR SELECT * FROM pg_database");
        if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            fprintf(stderr, "DECLARE CURSOR command failed\n");
            PQclear(res);
            exit_nicely(conn);
        }
        PQclear(res);
        res = PQexec(conn, "FETCH ALL in mycursor");
        if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
            PQclear(res);
            exit_nicely(conn);
        }
    
        /* first, print out the attribute names */
        nFields = PQnfields(res);
        for (i = 0; i < nFields; i++)
            printf("%-15s", PQfname(res, i));
        printf("\n\n");
    
        /* next, print out the rows */
        for (i = 0; i < PQntuples(res); i++)
        {
            for (j = 0; j < nFields; j++)
                printf("%-15s", PQgetvalue(res, i, j));
            printf("\n");
        }
        PQclear(res);
    
        /* close the cursor */
        res = PQexec(conn, "CLOSE mycursor");
        PQclear(res);
    
        /* commit the transaction */
        res = PQexec(conn, "COMMIT");
        PQclear(res);
    
        /* close the connection to the database and cleanup */
        PQfinish(conn);
    
        /* fclose(debug); */
        return 0;
    
    }

Example 1-2. libpq Example Program 2

    /*
     * testlibpq2.c
     *  Test of the asynchronous notification interface
     *
     * Start this program, then from psql in another window do
     *   NOTIFY TBL2;
     *
     * Or, if you want to get fancy, try this:
     * Populate a database with the following:
     *
     *   CREATE TABLE TBL1 (i int4);
     *
     *   CREATE TABLE TBL2 (i int4);
     *
     *   CREATE RULE r1 AS ON INSERT TO TBL1 DO
     *     (INSERT INTO TBL2 values (new.i); NOTIFY TBL2);
     *
     * and do
     *
     *   INSERT INTO TBL1 values (10);
     *
     */
    #include <stdio.h>
    #include "libpq-fe.h"
    
    void
    exit_nicely(PGconn *conn)
    {
        PQfinish(conn);
        exit(1);
    }
    
    main()
    {
        char       *pghost,
                   *pgport,
                   *pgoptions,
                   *pgtty;
        char       *dbName;
        int         nFields;
        int         i,
                    j;
    
        PGconn     *conn;
        PGresult   *res;
        PGnotify   *notify;
    
        /*
         * begin, by setting the parameters for a backend connection if the
         * parameters are null, then the system will try to use reasonable
         * defaults by looking up environment variables or, failing that,
         * using hardwired constants
         */
        pghost = NULL;              /* host name of the backend server */
        pgport = NULL;              /* port of the backend server */
        pgoptions = NULL;           /* special options to start up the backend
                                     * server */
        pgtty = NULL;               /* debugging tty for the backend server */
        dbName = getenv("USER");    /* change this to the name of your test
                                     * database */
    
        /* make a connection to the database */
        conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
    
        /*
         * check to see that the backend connection was successfully made
         */
        if (PQstatus(conn) == CONNECTION_BAD)
        {
            fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
            fprintf(stderr, "%s", PQerrorMessage(conn));
            exit_nicely(conn);
        }
    
        res = PQexec(conn, "LISTEN TBL2");
        if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            fprintf(stderr, "LISTEN command failed\n");
            PQclear(res);
            exit_nicely(conn);
        }
    
        /*
         * should PQclear PGresult whenever it is no longer needed to avoid
         * memory leaks
         */
        PQclear(res);
    
        while (1)
        {
    
            /*
             * wait a little bit between checks; waiting with select()
             * would be more efficient.
             */
            sleep(1);
            /* collect any asynchronous backend messages */
            PQconsumeInput(conn);
            /* check for asynchronous notify messages */
            while ((notify = PQnotifies(conn)) != NULL)
            {
                fprintf(stderr,
                     "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
                        notify->relname, notify->be_pid);
                free(notify);
            }
        }
    
        /* close the connection to the database and cleanup */
        PQfinish(conn);
    
        return 0;
    }

Example 1-3. libpq Example Program 3

    /*
     * testlibpq3.c Test the C version of Libpq, the PostgreSQL frontend
     * library. tests the binary cursor interface
     *
     *
     *
     * populate a database by doing the following:
     *
     * CREATE TABLE test1 (i int4, d real, p polygon);
     *
     * INSERT INTO test1 values (1, 3.567, polygon '(3.0, 4.0, 1.0, 2.0)');
     *
     * INSERT INTO test1 values (2, 89.05, polygon '(4.0, 3.0, 2.0, 1.0)');
     *
     * the expected output is:
     *
     * tuple 0: got i = (4 bytes) 1, d = (4 bytes) 3.567000, p = (4
     * bytes) 2 points   boundbox = (hi=3.000000/4.000000, lo =
     * 1.000000,2.000000) tuple 1: got i = (4 bytes) 2, d = (4 bytes)
     * 89.050003, p = (4 bytes) 2 points   boundbox =
     * (hi=4.000000/3.000000, lo = 2.000000,1.000000)
     *
     *
     */
    #include <stdio.h>
    #include "libpq-fe.h"
    #include "utils/geo_decls.h"    /* for the POLYGON type */
    
    void
    exit_nicely(PGconn *conn)
    {
        PQfinish(conn);
        exit(1);
    }
    
    main()
    {
        char       *pghost,
                   *pgport,
                   *pgoptions,
                   *pgtty;
        char       *dbName;
        int         nFields;
        int         i,
                    j;
        int         i_fnum,
                    d_fnum,
                    p_fnum;
        PGconn     *conn;
        PGresult   *res;
    
        /*
         * begin, by setting the parameters for a backend connection if the
         * parameters are null, then the system will try to use reasonable
         * defaults by looking up environment variables or, failing that,
         * using hardwired constants
         */
        pghost = NULL;              /* host name of the backend server */
        pgport = NULL;              /* port of the backend server */
        pgoptions = NULL;           /* special options to start up the backend
                                     * server */
        pgtty = NULL;               /* debugging tty for the backend server */
    
        dbName = getenv("USER");    /* change this to the name of your test
                                     * database */
    
        /* make a connection to the database */
        conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
    
        /*
         * check to see that the backend connection was successfully made
         */
        if (PQstatus(conn) == CONNECTION_BAD)
        {
            fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
            fprintf(stderr, "%s", PQerrorMessage(conn));
            exit_nicely(conn);
        }
    
        /* start a transaction block */
        res = PQexec(conn, "BEGIN");
        if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            fprintf(stderr, "BEGIN command failed\n");
            PQclear(res);
            exit_nicely(conn);
        }
    
        /*
         * should PQclear PGresult whenever it is no longer needed to avoid
         * memory leaks
         */
        PQclear(res);
    
        /*
         * fetch rows from the pg_database, the system catalog of
         * databases
         */
        res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR SELECT * FROM test1");
        if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
        {
            fprintf(stderr, "DECLARE CURSOR command failed\n");
            PQclear(res);
            exit_nicely(conn);
        }
        PQclear(res);
    
        res = PQexec(conn, "FETCH ALL in mycursor");
        if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
        {
            fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
            PQclear(res);
            exit_nicely(conn);
        }
    
        i_fnum = PQfnumber(res, "i");
        d_fnum = PQfnumber(res, "d");
        p_fnum = PQfnumber(res, "p");
    
        for (i = 0; i < 3; i++)
        {
            printf("type[%d] = %d, size[%d] = %d\n",
                   i, PQftype(res, i),
                   i, PQfsize(res, i));
        }
        for (i = 0; i < PQntuples(res); i++)
        {
            int        *ival;
            float      *dval;
            int         plen;
            POLYGON    *pval;
    
            /* we hard-wire this to the 3 fields we know about */
            ival = (int *) PQgetvalue(res, i, i_fnum);
            dval = (float *) PQgetvalue(res, i, d_fnum);
            plen = PQgetlength(res, i, p_fnum);
    
            /*
             * plen doesn't include the length field so need to
             * increment by VARHDSZ
             */
            pval = (POLYGON *) malloc(plen + VARHDRSZ);
            pval->size = plen;
            memmove((char *) &pval->npts, PQgetvalue(res, i, p_fnum), plen);
            printf("tuple %d: got\n", i);
            printf(" i = (%d bytes) %d,\n",
                   PQgetlength(res, i, i_fnum), *ival);
            printf(" d = (%d bytes) %f,\n",
                   PQgetlength(res, i, d_fnum), *dval);
            printf(" p = (%d bytes) %d points \tboundbox = (hi=%f/%f, lo = %f,%f)\n",
                   PQgetlength(res, i, d_fnum),
                   pval->npts,
                   pval->boundbox.xh,
                   pval->boundbox.yh,
                   pval->boundbox.xl,
                   pval->boundbox.yl);
        }
        PQclear(res);
    
        /* close the cursor */
        res = PQexec(conn, "CLOSE mycursor");
        PQclear(res);
    
        /* commit the transaction */
        res = PQexec(conn, "COMMIT");
        PQclear(res);
    
        /* close the connection to the database and cleanup */
        PQfinish(conn);
    
        return 0;
    }