Question

I am a newbie in using libpq and work on a postgresql database.

So, far I can insert/update/etc a postgresql database using C program, provided I give the actual values inside the quotes.

I want to know how to pass a string/integer variable in the command??

E.g. The following code adds a column called "comment" containing "TRUE" default value into an existing table "people". I need to update the value of the "comment" by "FALSE" where the id=2.

    #include <stdio.h>
    #include <stdlib.h>
    #include <libpq-fe.h>
    #include <string.h>

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

 int main()
 {
     PGconn *conn;
     PGresult *res;
 int nFields;
 int row_count=0,col_count=0;
 int row=0;
 int col=0;

 conn = PQconnectdb("dbname=test host=localhost user=postgres password=xxx");

     if(PQstatus(conn) == CONNECTION_BAD) 
     {
    fprintf(stderr, "Connection to database \"%s\" failed.\n", PQerrorMessage(conn));
            fprintf(stderr, "%s", PQerrorMessage(conn));
            exit_nicely(conn);
     }

res = PQexec(conn, "ALTER TABLE people ADD comment VARCHAR(50) DEFAULT 'TRUE'");
if((!res) || PQresultStatus(res) != PGRES_COMMAND_OK) 
{
    fprintf(stderr, "Adding col to table (ALTER) Failed: %s", PQerrorMessage(conn));
    PQclear(res);
    exit_nicely(conn);
    }

res = PQexec(conn, "SELECT * FROM people");
if((!res) || (PQresultStatus(res) != PGRES_TUPLES_OK))
    {
        fprintf(stderr, "SELECT command did not return tuples properly\n");
        PQclear(res);
    }

int query1 = 2;
res = PQexec(conn,"UPDATE people SET comment='FALSE' WHERE id =\'query1\'");
if((!res) || PQresultStatus(res) != PGRES_COMMAND_OK) 
{
    fprintf(stderr, "Insertion Failed: %s", PQerrorMessage(conn));
    PQclear(res);
    exit_nicely(conn);
}
else
    printf("Successfully inserted value in Table..... \n");

res = PQexec(conn, "SELECT * FROM people");
if((!res) || (PQresultStatus(res) != PGRES_TUPLES_OK))
    {
         fprintf(stderr, "SELECT command did not return tuples properly\n");
         PQclear(res);
    }

    puts("==========================");

for(row=0;row<PQntuples(res);row++) 
{
        for(col=0;col<PQnfields(res);col++) 
        {
            printf("%s\t", PQgetvalue(res, row, col));
        }
        puts("");
    }

PQclear(res);

    PQfinish(conn);

    return 0;
  }

I want the following output:

id | firstname | lastname | comment
1 | Fred | Flintstone | 5055551234 | TRUE
2 | Wilma | Flintstone | 5055551234 | FALSE
5 | XXX | YYY | 7633839276 | TRUE
3 | Barny | Rubble | 5055550000 | TRUE

However, I am getting the following error:

Insertion Failed: ERROR:  invalid input syntax for integer: "query1"
LINE 1: UPDATE people SET comment='FALSE' WHERE id ='query1'

Please help me with some suggestions.

Was it helpful?

Solution

There are two ways to handle this. The first is to prepare the string with the values inserted in it. The second is to use query parameters for which you can substitute values separately.

For the first method, you can use a function such as snprintf to prepare the command you will send to the server. For example:

char buffer[512];

int num=snprintf(buffer, sizeof(buffer), 
    "SELECT name FROM MYTABLE WHERE id=%d", id);

if (num>sizeof(buffer)) {
    /* error: buffer was too small */
}

After this buffer will contain the SQL query including the actual value of the variable id.

Note the need to check the return value from snprintf to see if the buffer overflowed.

Also note that when a string is being placed in the command, you need to ensure that the string does not contain any quotes or other special characters. If the string comes from outside your program, eg. From user input, then failing to quote it properly leaves a big hole through which someone could inject some malicious SQL. libpq provides the PQescapeLiteral function for this.

The other method, which is preferable in most cases, is to pass the SQL command and the parameters to the server separately. For example, you can do this using PQexecParams libpq functoin. Your SQL string would look like this:

PGresult r = PQexecParams(conn, /* Connection to database */
    "SELECT name FROM mytable WHERE id=$1",
    1,             /* Number of parameters */
    NULL,          /* NULL means server should figure out the parameter types */
    params,        /* Pointer to array of strings containing parameters */
    NULL,          /* Not needed unless binary format used */
    NULL,          /* Not needed unless binary format used */
    0              /* Result to come back in text format */
);

This function allows you to provide parameters and/or obtain results in either text or binary format. For simplicity my example above assumes text format for both.

A variation on this is to use prepared statements. In this case, you make two separate calls to libpq:

  1. Call PQprepare, to which you pass your SQL statement with parameter values $1, $2, etc, as per my example above. This will return a statement handle.

  2. Call PQexecPrepared, to which you pass the statement handle and also the parameters themselves, specified in a similar fashion to PQexecParams.

The advantage of using two steps like this is that you can prepare the statment once, and execute it many times, which reduces the amount of server overhead associated with parsing it and planning the query.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top