/*** stored Procedure: CREATE OR REPLACE PROCEDURE sql_select_data_procedure( fa integer, hold bool, INOUT blksize integer, INOUT fadata bytea ) LANGUAGE plpgsql AS $$ BEGIN IF (hold) THEN PERFORM pg_advisory_lock(fa); END IF; SELECT blk_size, data INTO blksize, fadata FROM fs_data WHERE file_address = fa; END; $$; ***/ #include #include #include #include #include // For htonl int main() { int nFields = 0; int nTuples = 0; int blk_size = 0; PGconn *shadow_db_conn; PGresult *res; const char *shadow_db_conn_info = "dbname=shadow_shc_data"; int is_shadow_db = 1; // Assuming it's a shadow database char *blk_size_val; char *data_val; // Connect to the shadow database if (is_shadow_db) { shadow_db_conn = PQconnectdb(shadow_db_conn_info); if (PQstatus(shadow_db_conn) != CONNECTION_OK) { fprintf(stderr, "Connection to shadow database failed: %s\n", PQerrorMessage(shadow_db_conn)); PQfinish(shadow_db_conn); exit(1); } // Set bytea_output to 'escape' res = PQexec(shadow_db_conn, "SET bytea_output = 'escape'"); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "SET bytea_output command failed: %s\n", PQerrorMessage(shadow_db_conn)); PQclear(res); PQfinish(shadow_db_conn); exit(1); } PQclear(res); printf("%s() Connection to shadow_shc_data database SUCCESSFUL\n", __func__); } // Construct the command to prepare char SelectDataName[11]; char SelectDataCommand[150]; int SelectDataNParams; Oid SelectDataParamTypes[2]; sprintf(SelectDataName,"%s","SelectData"); sprintf(SelectDataCommand, "CALL SQL_select_data_procedure($1, $2, NULL, NULL)"); SelectDataNParams = 2; SelectDataParamTypes[0] = 23; // int SelectDataParamTypes[1] = 16; // bool // Prepare the statement if (is_shadow_db) { res = PQprepare(shadow_db_conn, SelectDataName, SelectDataCommand, SelectDataNParams, SelectDataParamTypes); if (PQresultStatus(res) != PGRES_COMMAND_OK) { fprintf(stderr, "Prepare failed: %s\n", PQerrorMessage(shadow_db_conn)); PQclear(res); PQfinish(shadow_db_conn); exit(1); } PQclear(res); } // Sample input values int32_t fa = -335509949; bool hold = false; uint32_t fa2 = htonl(fa); char *fa_val = (char *)&fa2; bool hold2 = hold; char *hold_val = (char *)&hold2; const char *paramValues[2] = {fa_val, hold_val}; int paramLengths[2] = {sizeof(fa2), sizeof(hold2)}; int paramFormats[2] = {1, 1}; // identify parameter as binary // Assuming paramValues, paramLengths, and paramFormats are properly populated // Execute the prepared statement if (is_shadow_db) { //const char *paramValues[2] = {"123", "true"}; //int paramLengths[2] = {sizeof("123") - 1, sizeof("true") - 1}; // Minus 1 for excluding null terminator //int paramFormats[2] = {0, 0}; // Assuming all parameters are in text format int resultFormat = 1; // 1 for binary result format res = PQexecPrepared(shadow_db_conn, SelectDataName, SelectDataNParams, paramValues, paramLengths, paramFormats, resultFormat); if (PQresultStatus(res) == PGRES_TUPLES_OK && PQnfields(res) != 0 && PQntuples(res) > 0) { //printf("SELECT operation succeeded on Shadow DB\n"); // Process the result if needed nFields = PQnfields(res); // number of columns nTuples = PQntuples(res); // number of rows printf("%s() nFields(cols)=%i nTuples(rows)=%i\n",__func__,nFields,nTuples); blk_size_val = PQgetvalue(res, 0, 0); data_val = PQgetvalue(res, 0, 1); if(blk_size_val != NULL && data_val != NULL) { printf("SELECT operation succeeded on Shadow DB\n"); blk_size = ntohl(*(uint32_t *)PQgetvalue (res, 0, 0)); printf("%s() blk_size returned is %i\n",__func__,blk_size); } } else { fprintf(stderr, "SELECT failed on Shadow DB: %s\n", PQerrorMessage(shadow_db_conn)); } PQclear(res); } PQfinish(shadow_db_conn); // Close the connection return 0; }