Correct way to bind numeric values to prepared sql - c++

I haven't been working with libpq-fe, (postgresql-9.1.3)
PGresult * pg_res;
char * sql = "INSERT INTO tbGroups (Group_UID, Full_Name, User_UID) VALUES ($1, $2, $3);";
int group_uid = 11;
int user_uid = 1;
const char * name = "TEST1";
const char * values[3] = {(const char *) &group_uid, name, (const char *) &user_uid};
int lengths[3] = {sizeof(group_uid), strlen(name), sizeof(user_uid)};
int format[3] = {1, 1, 1};
pg_res = PQprepare(conn, "insert_tbgroups", sql, 3, NULL);
PQclear(pg_res);
pg_res = PQexecPrepared(conn, "insert_tbgroups", 3, values, lengths, format, 1);
PQclear(pg_res);
Works, but result is:
rcpdv=# select group_uid, full_name, user_uid from tbGroups;
group_uid | full_name | user_uid
-----------+---------------+----------
184549376 | TEST1 | 16777216
(1 rows)
What is correct way to bind numeric values to prepared sql, without param_types?

PostgreSQL is expecting the data to come across a network connection. So you have to convert your numerical data into network format (big endian). I typically use ntohl() functions, for a crude example in your case:
int format[3] = {1, 1, 1};
for (i = 0; i < 3; ++i) {
format[i] = ntohl(format[i]);
}

Related

Can't run sha256 more than once in intel sgx enclave

So I'm trying to create two sha256 hashes in intel sgx using their cyrpto library. Currently, if I run the following:
sgx_sha256_hash_t *hash1;
int first = 1;
sgx_status_t = stat;
stat = sgx_sha256_msg( ( uint8_t * ) &first, 8, hash1 );
I have no problems, and I properly get hash1, however if I try
sgx_sha256_hash_t *hash1;
sgx_sha256_hash_t *hash2;
int first = 1;
int second = 2;
sgx_status_t = stat;
stat = sgx_sha256_msg( ( uint8_t * ) &first, 8, hash1 );
stat = sgx_sha256_msg( ( uint8_t * ) &second, 8, hash2 );
I get a segmentation fault. I tried doing this with the sha init, update, get_hash and close method instead, but with no imporved results, does anyone know why this might be? I was thinking I might be running out of memory in the enclave, if that's true, is there a way to expand my enclave?
You are writing your hashes to a random location in memory through those two uninitialised pointers, hence the segfaults. Also, your src_len parameters are incorrect, and for completeness the first parameter should be const.
So, what you want is:
sgx_sha256_hash_t hash1; // note: no asterisk
sgx_sha256_hash_t hash2;
int first = 1;
int second = 2;
sgx_status_t = stat;
stat = sgx_sha256_msg( ( const uint8_t * ) &first, sizeof (first), &hash1 );
stat = sgx_sha256_msg( ( const uint8_t * ) &second, sizeof (second), &hash2 );

How to insert array of bytes in PostgreSQL table via libpq C++ API

I am trying to update table
CREATE TABLE some_table
(
id integer NOT NULL,
client_fid bigint NOT NULL,
index bytea[],
update_time timestamp without time zone
)
WITH (
OIDS = FALSE
using modified code snipped from here How to insert text array in PostgreSQL table in binary format using libpq?
#define BYTEAARRAYOID 1001
#define BYTEAOID 17
Here is a pgvals_t structure definition
struct pgvals_t
{
/* number of array dimensions */
int32_t ndims;
/* flag describing if array has NULL values */
int32_t hasNull;
/* Oid of data stored in array. In our case is 25 for TEXT */
Oid oidType;
/* Number of elements in array */
int32_t totalLen;
/* Not sure for this one.
I think it describes dimensions of elements in case of arrays storing arrays */
int32_t subDims;
/* Here our data begins */
} __attribute__ ((__packed__));
I've removed dataBegins pointer from struct as it affects data layout in memo
std::size_t nElems = _data.size();
uint32_t valsDataSize = sizeof(prx::pgvals_t) + sizeof(int32_t) * nElems +
sizeof(uint8_t)*nElems;
void *pData = malloc(valsDataSize);
prx::pgvals_t* pvals = (prx::pgvals_t*)pData;
/* our array has one dimension */
pvals->ndims = ntohl(1);
/* our array has no NULL elements */
pvals->hasNull = ntohl(0);
/* type of our elements is bytea */
pvals->oidType = ntohl(BYTEAOID);
/* our array has nElems elements */
pvals->totalLen = ntohl(nElems);
pvals->subDims = ntohl(1);
int32_t elemLen = ntohl(sizeof(uint8_t));
std::size_t offset = sizeof(elemLen) + sizeof(_data[0]);
char * ptr = (char*)(pvals + sizeof(prx::pgvals_t));
for(auto byte : _data){
memcpy(ptr, &elemLen, sizeof(elemLen));
memcpy(ptr + sizeof(elemLen), &byte, sizeof(byte));
ptr += offset;
}
Oid paramTypes[] = { BYTEAARRAYOID };
char * paramValues[] = {(char* )pData};
int paramLengths[] = { (int)valsDataSize };
int paramFormats[] = {1};
PGresult *res = PQexecParams(m_conn, _statement.c_str(),
1,
paramTypes,
paramValues,
paramLengths,
paramFormats,
1
);
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
std::string errMsg = PQresultErrorMessage(res);
PQclear(res);
throw std::runtime_error(errMsg);
}
free(pData);
The binary data is contained in std::vector variable and am using the following query in a _statement variable of type std::string
INSERT INTO some_table \
(id, client_id, \"index\", update_time) \
VALUES \
(1, 2, $1, NOW())
Now after call to PQExecParams I am get an exception with message
"incorrect binary data format in bind parameter 1"
What can be the problem here?
If you want to pass a bytea[] in binary format, you have to use the binary array format as read by array_recv and written by array_send.
You cannot just pass a C array.

VARIANT export/import C++ DLL SAFEARRAY

I know that this topic is quite popular. However, I'd like to solve a simple problem... My target is to create a DLL in C++ able to import and export data matrices from VB (Excel or other programs). I read in some blogs that a common way to do that is to use the SAFEARRAYs.
So, I created the following C++ code:
VARIANT _stdcall ReadArrayVBA_v1(VARIANT *Input0) {
double dm = 0, rm = 0;
//OUTPUT DATA DEFINITION
VARIANT v;
SAFEARRAYBOUND Dim[1];
Dim[0].lLbound = 0; Dim[0].cElements = 4;
v.vt = VT_R8;
v.parray = SafeArrayCreate(VT_R8, 1, Dim);
//==============================================
SAFEARRAY* pSafeArrayInput0 = NULL; //Define a pointer SAFEARRAY Type
pSafeArrayInput0 = *V_ARRAYREF(Input0);
long lLBound = -1, lUBound = 1; //Preset dimension
SafeArrayGetLBound(pSafeArrayInput0, 1, &lLBound);
SafeArrayGetUBound(pSafeArrayInput0, 1, &lUBound);
long CntElements = lUBound - lLBound + 1;
long Index[1];
for (int i=0; i<CntElements; i++){
Index[0] = i;
SafeArrayGetElement(pSafeArrayInput0, Index, &dm);
rm = dm + 1;
SafeArrayPutElement(v.parray, Index, &rm);
}
return v;
}
It compiles and I call from VBA Excel in the following manner:
Private Declare Function ReadArrayVBA_v1 Lib "[PATH]\VARIANTtest.dll" (ByRef Input0 As Variant) As Variant
Sub VBACall()
Dim InputR0(1 To 4) As Variant
Dim vResult1 As Variant
InputR0(1) = 2
InputR0(2) = 20
InputR0(3) = 200
InputR0(4) = 240
vResult1 = ReadArrayVBA_v1(InputR0)
End Sub
The function gives me back values such as 1.2E-305 and similar. Why?

SQLITE_MISUSE in prepared statement

I'm getting a SQLITE_MISUSE error on the following code, and I am wondering if it might be caused by having the table name be a bound parameter? What are some different causes of SQLITE_MISUE?
const char sqlNeuralStateInsert[] =
"INSERT INTO ?1(LAYER_ID, NEURON_ID, INPUT_ID, VALUE)"
"VALUES(?2, ?3, ?4, ?5);";
sqlite3_stmt* stmt1;
rc = sqlite3_prepare_v2(db, sqlNeuralStateInsert, -1, &stmt1, NULL);
if(rc){
//!< Failed to prepare insert statement
}
sqlite3_bind_text(stmt1, 1, this->getNName().c_str(), -1, SQLITE_STATIC);
for(uint32_t i = 0; i < m_nlayers; i++){
sqlite3_bind_int(stmt1, 2, i); // Layer id
for(uint32_t j = 0; j < m_layers[i]->getNeuronCount(); j++){
std::vector<double> weights = m_layers[i]->getWeights(j);
sqlite3_bind_int(stmt1, 3, j); // Neuron id
for(uint32_t k = 0; k < weights.size(); k++){
sqlite3_bind_int(stmt1, 4, k);
sqlite3_bind_double(stmt1, 5, weights[k]);
rc = sqlite3_step(stmt1);
printf("%d\n", rc);
}
}
}
sqlite3_finalize(stmt1);
You're right; you cannot bind the table name:
Generally one cannot use SQL parameters/placeholders for database identifiers (tables, columns, views, schemas, etc.) or database functions (e.g., CURRENT_DATE), but instead only for binding literal values.
You could have trivially tested this hypothesis by hard-coding the table name.

SQLite multi insert from C++ just adding the first one

I have the following code for SQLite:
std::vector<std::vector<std::string> > InternalDatabaseManager::query(std::string query)
{
sqlite3_stmt *statement;
std::vector<std::vector<std::string> > results;
if(sqlite3_prepare_v2(internalDbManager, query.c_str(), -1, &statement, 0) == SQLITE_OK)
{
int cols = sqlite3_column_count(statement);
int result = 0;
while(true)
{
result = sqlite3_step(statement);
std::vector<std::string> values;
if(result == SQLITE_ROW)
{
for(int col = 0; col < cols; col++)
{
std::string s;
char *ptr = (char*)sqlite3_column_text(statement, col);
if(ptr) s = ptr;
values.push_back(s);
}
results.push_back(values);
} else
{
break;
}
}
sqlite3_finalize(statement);
}
std::string error = sqlite3_errmsg(internalDbManager);
if(error != "not an error") std::cout << query << " " << error << std::endl;
return results;
}
When I try to pass a query string like:
INSERT INTO CpuUsage (NODE_ID, TIME_ID, CORE_ID, USER, NICE, SYSMODE, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST) VALUES (1, 1, -1, 1014711, 117915, 175551, 5908257, 112996, 2613, 4359, 0, 0); INSERT INTO CpuUsage (NODE_ID, TIME_ID, CORE_ID, USER, NICE, SYSMODE, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST) VALUES (1, 1, 0, 1014711, 117915, 175551, 5908257, 112996, 2613, 4359, 0, 0); INSERT INTO CpuUsage (NODE_ID, TIME_ID, CORE_ID, USER, NICE, SYSMODE, IDLE, IOWAIT, IRQ, SOFTIRQ, STEAL, GUEST) VALUES (1, 1, 1, 1014711, 117915, 175551, 5908257, 112996, 2613, 4359, 0, 0);
It results just inserting the first insert. Using some other tool lite SQLiteStudio it performs ok.
Any ideas to help me, please?
Thanks,
Pedro
EDIT
My query is a std::string.
const char** pzTail;
const char* q = query.c_str();
int result = -1;
do {
result = sqlite3_prepare_v2(internalDbManager, q, -1, &statement, pzTail);
q = *pzTail;
}
while(result == SQLITE_OK);
This gives me Description: cannot convert ‘const char*’ to ‘const char**’ for argument ‘5’ to ‘int sqlite3_prepare_v2(sqlite3*, const char*, int, sqlite3_stmt*, const char*)’
SQLite's prepare_v2 will only create a statement from the first insert in your string. You can think of it as a "pop front" mechanism.
int sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
From http://www.sqlite.org/c3ref/prepare.html
If pzTail is not NULL then *pzTail is made to point to the first byte
past the end of the first SQL statement in zSql. These routines only
compile the first statement in zSql, so *pzTail is left pointing to
what remains uncompiled.
The pzTail parameter will point to the rest of the inserts, so you can loop through them all until they have all been prepared.
The other option is to only do one insert at a time, which makes the rest of your handling code a little bit simpler usually.
Typically I have seen people do this sort of thing under the impression that they will be evaluated under the same transaction. This is not the case, though. The second one may fail and the first and third will still succeed.