#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <libpq-fe.h>
#define TOTAL_QUERIES 1000000
#define QUERIES_PER_BATCH 1000
#define BATCHES (TOTAL_QUERIES / QUERIES_PER_BATCH)
double get_time_ms() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0;
}
int main() {
printf("🔧 1 MILLION QUERY BENCHMARK - C libpq\n");
printf("======================================\n");
printf("Total queries: %15d\n", TOTAL_QUERIES);
printf("Batch size: %15d\n", QUERIES_PER_BATCH);
printf("Batches: %15d\n", BATCHES);
printf("\n");
PGconn *conn = PQconnectdb("host=127.0.0.1 port=5432 user=orion dbname=example_staging");
if (PQstatus(conn) != CONNECTION_OK) {
fprintf(stderr, "Connection failed: %s\n", PQerrorMessage(conn));
PQfinish(conn);
return 1;
}
printf("✅ Connected to PostgreSQL\n");
PGresult *res = PQprepare(conn, "stmt1",
"SELECT id, name FROM harbors LIMIT $1", 1, NULL);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Prepare failed: %s\n", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
return 1;
}
PQclear(res);
printf("✅ Statement prepared\n\n");
printf("📊 Executing %d queries...\n\n", TOTAL_QUERIES);
double start = get_time_ms();
int successful = 0;
if (PQenterPipelineMode(conn) == 0) {
fprintf(stderr, "Failed to enter pipeline mode\n");
PQfinish(conn);
return 1;
}
for (int batch = 0; batch < BATCHES; batch++) {
for (int i = 0; i < QUERIES_PER_BATCH; i++) {
char param[16];
snprintf(param, sizeof(param), "%d", (i % 10) + 1);
const char *paramValues[1] = {param};
if (PQsendQueryPrepared(conn, "stmt1", 1, paramValues, NULL, NULL, 0) == 0) {
fprintf(stderr, "Send failed: %s\n", PQerrorMessage(conn));
break;
}
}
PQpipelineSync(conn);
for (int i = 0; i < QUERIES_PER_BATCH; i++) {
res = PQgetResult(conn);
if (res == NULL) break;
if (PQresultStatus(res) == PGRES_TUPLES_OK) {
successful++;
}
PQclear(res);
res = PQgetResult(conn);
if (res) PQclear(res);
}
res = PQgetResult(conn);
if (res) PQclear(res);
if ((batch + 1) % 100 == 0) {
double elapsed = (get_time_ms() - start) / 1000.0;
double qps = successful / elapsed;
int remaining = TOTAL_QUERIES - successful;
double eta = remaining / qps;
printf(" Batch %d/%d: %.0f q/s | ETA: %.0fs\n",
batch + 1, BATCHES, qps, eta);
}
}
PQexitPipelineMode(conn);
double elapsed = (get_time_ms() - start) / 1000.0;
double qps = TOTAL_QUERIES / elapsed;
double per_query_ns = (elapsed * 1000000000.0) / TOTAL_QUERIES;
printf("\n📈 FINAL RESULTS:\n");
printf("┌──────────────────────────────────────────┐\n");
printf("│ 1 MILLION QUERIES - C libpq │\n");
printf("├──────────────────────────────────────────┤\n");
printf("│ Total Time: %20.1fs │\n", elapsed);
printf("│ Queries/Second: %20.0f │\n", qps);
printf("│ Per Query: %17.0fns │\n", per_query_ns);
printf("│ Successful: %20d │\n", successful);
printf("└──────────────────────────────────────────┘\n");
PQfinish(conn);
return 0;
}