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.
Related
I have a nested table in my lua code that I want to pass to C++ so the native code can manipulate it:
-- Some persistent data in my game
local data = {
{ 44, 34, 0, 7, },
{ 4, 4, 1, 3, },
}
-- Pass it into a C++ function that can modify the input data.
TimelineEditor(data)
How do I write my C++ code to read the nested table and modify its values?
Reading Lua nested tables in C++ and lua c read nested tables both describe how I can read from nested tables, but not how to write to them.
Short answer
Lua uses a stack to get values in and out of tables. To modify table values you'll need to push the table you want to modify with lua_rawgeti, push a value you want to insert with lua_pushinteger, and then set the value in the table with lua_rawseti.
When writing this, it's important to visualize the stack to ensure you use the right indexes:
lua_rawgeti()
stack:
table
lua_rawgeti()
stack:
number <-- top of the stack
table
lua_tonumber()
stack:
number
table
lua_pop()
stack:
table
lua_pushinteger()
stack:
number
table
lua_rawseti()
stack:
table
Negative indexes are stack positions and positive indexes are argument positions. So we'll often pass -1 to access the table at the stack. When calling lua_rawseti to write to the table, we'll pass -2 since the table is under the value we're writing.
Example
I'll add inspect.lua to the lua code to print out the table values so we can see that the values are modified.
local inspect = require "inspect"
local data = {
{ 44, 34, 0, 7, },
{ 4, 4, 1, 3, },
}
print("BEFORE =", inspect(data, { depth = 5, }))
TimelineEditor(data)
print("AFTER =", inspect(data, { depth = 5, }))
Assuming you've figured out BindingCodeToLua, you can implement the function like so:
// Replace LOG with whatever you use for logging or use this:
#define LOG(...) printf(__VA_ARGS__); printf("\n")
// I bound with Lunar. I don't think it makes a difference for this example.
int TimelineEditor(lua_State* L)
{
LOG("Read the values and print them out to show that it's working.");
{
int entries_table_idx = 1;
luaL_checktype(L, entries_table_idx, LUA_TTABLE);
int n_entries = static_cast<int>(lua_rawlen(L, entries_table_idx));
LOG("%d entries", n_entries);
for (int i = 1; i <= n_entries; ++i)
{
// Push inner table onto stack.
lua_rawgeti(L, entries_table_idx, i);
int item_table_idx = 1;
luaL_checktype(L, -1, LUA_TTABLE);
int n_items = static_cast<int>(lua_rawlen(L, -1));
LOG("%d items", n_items);
for (int i = 1; i <= n_items; ++i)
{
// Push value from table onto stack.
lua_rawgeti(L, -1, i);
int is_number = 0;
// Read value
int x = static_cast<int>(lua_tonumberx(L, -1, &is_number));
if (!is_number)
{
// fire an error
luaL_checktype(L, -1, LUA_TNUMBER);
}
LOG("Got: %d", x);
// pop value off stack
lua_pop(L, 1);
}
// pop table off stack
lua_pop(L, 1);
}
}
LOG("Overwrite the values");
{
int entries_table_idx = 1;
luaL_checktype(L, entries_table_idx, LUA_TTABLE);
int n_entries = static_cast<int>(lua_rawlen(L, entries_table_idx));
LOG("%d entries", n_entries);
for (int i = 1; i <= n_entries; ++i)
{
// Push inner table onto stack.
lua_rawgeti(L, entries_table_idx, i);
int item_table_idx = 1;
luaL_checktype(L, -1, LUA_TTABLE);
int n_items = static_cast<int>(lua_rawlen(L, -1));
LOG("%d items", n_items);
for (int j = 1; j <= n_items; ++j)
{
int x = j + 10;
// Push new value onto stack.
lua_pushinteger(L, x);
// rawseti pops the value off. Need to go -2 to get to the
// table because the value is on top.
lua_rawseti(L, -2, j);
LOG("Wrote: %d", x);
}
// pop table off stack
lua_pop(L, 1);
}
}
// No return values
return 0;
}
Output:
BEFORE = { { 44, 34, 0, 7 }, { 4, 4, 1, 3 } }
Read the values and print them out to show that it's working.
2 entries
4 items
Got: 44
Got: 34
Got: 0
Got: 7
4 items
Got: 4
Got: 4
Got: 1
Got: 3
Overwrite the values
2 entries
4 items
Wrote: 11
Wrote: 12
Wrote: 13
Wrote: 14
4 items
Wrote: 11
Wrote: 12
Wrote: 13
Wrote: 14
AFTER = { { 11, 12, 13, 14 }, { 11, 12, 13, 14 } }
I'm trying to merge a collection of dictionaries into the root process. Here's a short example:
#define MAX_CF_LENGTH 55
map<string, int> dict;
if (rank == 0)
{
dict = {
{"Accelerator Defective", 33},
{"Aggressive Driving/Road Rage", 27},
{"Alcohol Involvement", 19},
{"Animals Action", 30}};
}
if (rank == 1)
{
dict = {
{"Driver Inexperience", 6},
{"Driverless/Runaway Vehicle", 46},
{"Drugs (Illegal)", 38},
{"Failure to Keep Right", 24}};
}
if (rank == 2)
{
dict = {
{"Lost Consciousness", 1},
{"Obstruction/Debris", 8},
{"Other Electronic Device", 25},
{"Other Lighting Defects", 43},
{"Other Vehicular", 7}};
}
Scatterer scatterer(rank, MPI_COMM_WORLD, num_workers);
scatterer.gatherDictionary(dict, MAX_CF_LENGTH);
The idea inside gatherDictionary() is to put every key in a char array at each process (duplicates are allowed). After that, gathering all keys into the root and creating the final (merged) dictionary before broadcasting it. Here's the code:
void Scatterer::gatherDictionary(map<string,int> &dict, int maxKeyLength)
{
// Calculate destination dictionary size
int numKeys = dict.size();
int totalLength = numKeys * maxKeyLength;
int finalNumKeys = 0;
MPI_Reduce(&numKeys, &finalNumKeys, 1, MPI_INT, MPI_SUM, 0, comm);
// Computing number of elements that are received from each process
int *recvcounts = NULL;
if (rank == 0)
recvcounts = new int[num_workers];
MPI_Gather(&totalLength, 1, MPI_INT, recvcounts, 1, MPI_INT, 0, comm);
// Computing displacement relative to recvbuf at which to place the incoming data from each process
int *displs = NULL;
if (rank == 0)
{
displs = new int[num_workers];
displs[0] = 0;
for (int i = 1; i < num_workers; i++)
displs[i] = displs[i - 1] + recvcounts[i - 1] + 1;
}
char(*dictKeys)[maxKeyLength];
char(*finalDictKeys)[maxKeyLength];
dictKeys = (char(*)[maxKeyLength])malloc(numKeys * sizeof(*dictKeys));
if (rank == 0)
finalDictKeys = (char(*)[maxKeyLength])malloc(finalNumKeys * sizeof(*finalDictKeys));
// Collect keys for each process
int i = 0;
for (auto pair : dict)
{
strncpy(dictKeys[i], pair.first.c_str(), maxKeyLength);
i++;
}
MPI_Gatherv(dictKeys, totalLength, MPI_CHAR, finalDictKeys, recvcounts, displs, MPI_CHAR, 0, comm);
// Create new dictionary and distribute it to all processes
dict.clear();
if (rank == 0)
{
for (int i = 0; i < finalNumKeys; i++)
dict[finalDictKeys[i]] = dict.size();
}
delete[] dictKeys;
if (rank == 0)
{
delete[] finalDictKeys;
delete[] recvcounts;
delete[] displs;
}
broadcastDictionary(dict, maxKeyLength);
}
I'm sure of broadcastDicitonary() correctness as I've already tested it. Debugging into the gathering function I'm getting the following partial results:
Recvcounts:
220
220
275
Displacements:
0
221
442
FinalDictKeys:
Rank:0 Accelerator Defective
Rank:0 Aggressive Driving/Road Rage
Rank:0 Alcohol Involvement
Rank:0 Animals Action
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Since only root data is being collected I'm wondering if this has something to do with the characters allocation even if it should be contiguous. I don't think this is related to a missing null character at the end since there's already a lot of padding for each string/key.
Thanks in advance for pointing out any missings or improvements and please comment if you need any extra infos.
If you wish to test it yourself I've put in a one-file only the code all together, it is compile&run ready (of course this works with 3 mpi processes). Code Here
displs[i] = displs[i - 1] + recvcounts[i - 1] + 1;
That + 1 at the end is superfluous. Change it to:
displs[i] = displs[i - 1] + recvcounts[i - 1];
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]);
}
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.
I'm trying to execute a query in PostgreSQL using the following code. It's written in C/C++ and I keep getting the following error when declaring a cursor:
DECLARE CURSOR failed: ERROR: could not determine data type of parameter $1
Searching here and on google, I can't find a solution. Can anyone find where I have made and error and why this is happening?
void searchdb( PGconn *conn, char* name, char* offset )
{
// Will hold the number of field in table
int nFields;
// Start a transaction block
PGresult *res = PQexec(conn, "BEGIN");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printf("BEGIN command failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}
// Clear result
PQclear(res);
printf("BEGIN command - OK\n");
//set the values to use
const char *values[3] = {(char*)name, (char*)RESULTS_LIMIT, (char*)offset};
//calculate the lengths of each of the values
int lengths[3] = {strlen((char*)name), sizeof(RESULTS_LIMIT), sizeof(offset)};
//state which parameters are binary
int binary[3] = {0, 0, 1};
res = PQexecParams(conn, "DECLARE emprec CURSOR for SELECT name, id, 'Events' as source FROM events_basic WHERE name LIKE '$1::varchar%' UNION ALL "
" SELECT name, fsq_id, 'Venues' as source FROM venues_cache WHERE name LIKE '$1::varchar%' UNION ALL "
" SELECT name, geo_id, 'Cities' as source FROM static_cities WHERE name LIKE '$1::varchar%' OR FIND_IN_SET('$1::varchar%', alternate_names) != 0 LIMIT $2::int4 OFFSET $3::int4",
3, //number of parameters
NULL, //ignore the Oid field
values, //values to substitute $1 and $2
lengths, //the lengths, in bytes, of each of the parameter values
binary, //whether the values are binary or not
0); //we want the result in text format
// Fetch rows from table
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
printf("DECLARE CURSOR failed: %s", PQerrorMessage(conn));
PQclear(res);
exit_nicely(conn);
}
// Clear result
PQclear(res);
res = PQexec(conn, "FETCH ALL in emprec");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
printf("FETCH ALL failed");
PQclear(res);
exit_nicely(conn);
}
// Get the field name
nFields = PQnfields(res);
// Prepare the header with table field name
printf("\nFetch record:");
printf("\n********************************************************************\n");
for (int i = 0; i < nFields; i++)
printf("%-30s", PQfname(res, i));
printf("\n********************************************************************\n");
// Next, print out the record for each row
for (int i = 0; i < PQntuples(res); i++)
{
for (int j = 0; j < nFields; j++)
printf("%-30s", PQgetvalue(res, i, j));
printf("\n");
}
PQclear(res);
// Close the emprec
res = PQexec(conn, "CLOSE emprec");
PQclear(res);
// End the transaction
res = PQexec(conn, "END");
// Clear result
PQclear(res);
}
Try replacing
WHERE name LIKE '$1::varchar%'
with
WHERE name LIKE ($1::varchar || '%')
Treat all other occurances of '$1::varchar%' similarly.
More information on string concatenation in the manual.