Postgres database connection (a database handle):
db_connection = PQconnectdb("dbname = 'NAME_OF_DATABASE' user = 'USERNAME' password = 'PASSWORD'");
if (PQstatus(db_connection) != CONNECTION_OK)
{
printf ("Connection to database failed: %s", PQerrorMessage(db_connection));
PQfinish (db_connection);
exit (FAILURE);
}
strncpy (&db_statement[0], "SELECT students.student_id, students.first_name, students.last_name FROM students ORDER BY students.student_id ASC", MAX_DB_STATEMENT_BUFFER_LENGTH);
db_result = PQexec (db_connection, &db_statement[0]);
if (PQresultStatus(db_result) == PGRES_TUPLES_OK)
{
num_rows = PQntuples(db_result);
if (num_rows == 0)
{
printf ("database is empty");
}
else
{
for (row = 0; row < num_rows; row++)
{
printf ("%s %s %s\n", PQgetvalue (db_result, row, 0), PQgetvalue (db_result, row, 1), PQgetvalue (db_result, row, 2));
}
}
PQclear (db_result);
}
The PQexec() command executes an SQL statement.
Watch out for SQL-injection attacks!
Imagine a query such as this:snprintf (&db_statement[0], MAX_DB_STATEMENT_SIZE-1, "INSERT INTO students (first_name, last_name) VALUES ('Rob', 'Bruce')");
Now imagine we insert the first_name and last_name as character string arrays dynamically to build our SQL query:snprintf (&db_statement[0], MAX_DB_STATEMENT_SIZE-1, "INSERT INTO students (first_name, last_name) VALUES ('%s', '%s')", &first_name[0], &last_name[0]);
Let first_name be the following literal string (in blue):Ha', 'Ha'); DELETE FROM students; INSERT INTO students (first_name, last_name) VALUES ('Your data
Let last_name is the following literal string (in green):is gone
When these variables are substituted into our snprintf() statement, the resulting SQL query is as follows:
INSERT INTO students (first_name, last_name) VALUES ('Ha', 'Ha'); DELETE FROM students; INSERT INTO students (first_name, last_name) VALUES ('Your data', 'is gone');
From previous slide, the resulting SQL injection query is as follows:
INSERT INTO students (first_name, last_name) VALUES ('Ha', 'Ha'); DELETE FROM students; INSERT INTO students (first_name, last_name) VALUES ('Your data', 'is gone');
When executed by Postgres, the statement above will actually execute three commands:INSERT INTO students (first_name, last_name) VALUES ('Ha', 'Ha');
DELETE FROM students;
INSERT INTO students (first_name, last_name) VALUES ('Your data', 'is gone');
This is an SQL injection attack with really nasty consequences!
Be cautious when using PQexec() to execute the resultant SQL query!
To avoid SQL injection attacks, use PQexecParams() instead.
parameter_values[0] = &student_first_name[0];
parameter_values[1] = &student_last_name[0];
strncpy (&db_statement[0], "INSERT INTO students (first_name, last_name) VALUES ($1, $2) RETURNING student_id", MAX_DB_STATEMENT_BUFFER_LENGTH);
db_result = PQexecParams (db_connection, db_statement, 2, NULL, parameter_values, NULL, NULL, 0);
if (PQresultStatus(db_result) != PGRES_TUPLES_OK)
{
printf ("Postgres INSERT error: %s\n", PQerrorMessage(db_connection));
}
else
{
if (PQntuples(db_result) == 1)
{
if (strlen(PQgetvalue(db_result, 0, 0)) < MAX_STUDENT_ID_LENGTH-1)
{
strncpy (&student_id[0], PQgetvalue(db_result, 0, 0), MAX_STUDENT_ID_LENGTH-1);
printf ("Student ID %s: assigned to %s %s\n\n", &student_id[0], &student_first_name[0], &student_last_name[0]);
}
}
PQclear(db_result);
}
Examine, compile, and experiment with my example C program, db_menu
Spring 2016, CS-161:
Lectures
Assignments:
Programs: