Using sqlite3_bind_XXX inside a loop - c++

I want to do multiple parameterized inserts with SQLite in my code. For this :
I have a single prepare statement outside of my loop as :
error = sqlite3_prepare(connection, insert_sql, strlen(insert_sql), &stmt, NULL);
I want inserts within a loop as:
while ( not reached end of datafile ) {
// Insert into server table
sqlite3_bind_int(stmt, 1, id1);
sqlite3_bind_double(stmt, 2, latitude);
sqlite3_bind_double(stmt, 3, longitude);
sqlite3_step(stmt);
}
The API docs for the function : https://www.sqlite.org/c3ref/bind_blob.html
mention that :
sqlite3_step() has been called more recently than sqlite3_reset(), then the call will return SQLITE_MISUSE
Bindings are not cleared by the sqlite3_reset() routine
If any sqlite3_bind_() routine is passed a prepared statement that has
been finalized, the result is undefined and probably harmful.
I am really confused as to how do I do repeated inserts with parameterized query in SQLite?

Just call sqlite3_reset() after sqlite3_step().

Related

Try to get blob data from Oracle by OCI routines but get error: ORA-01008: not all variables bound

I try to get blob data from Oracle by OCI routines.
I use the next code but the exceute statement gives ther error: ORA-01008: not all variables bound
What do I wrong? Can anybody help me?
Thanks,
Kees Braaksma
void get_blob_data()
{
// The query
// The results of this methode
// if errstring is empty, the blob data can be found in the 4th parameter.
// otherwise the error is given in errstring
CString csQuery;
csQuery.Format("BEGIN get_blob('%s','%ld',:ERRSTRING,:BLOB); END;", "20", 200);
//init
OCIHandleAlloc((dvoid *)m_OCIEnvironment , (dvoid **)(&m_OCIStatement),
(ub4)OCI_HTYPE_STMT, (size_t)0, (dvoid **)0);
//Prepare statement voor query
OCIStmtPrepare(m_OCIStatement, m_OCIError, (text *)(csQuery),
(ub4)(strlen(csQuery)), (ub4)OCI_NTV_SYNTAX, (ub4)OCI_DEFAULT);
// output variables
char *pszResult = (char*)malloc(256);
memset(pszResult, 0, sizeof(pszResult));
Blob *blob = new Blob();
m_pIndicator1 = malloc(sizeof(OCIInd));
m_pDefine1 = NULL;
OCIDefineByPos(m_OCIStatement, &m_pDefine1, m_OCIError, (ub4)1,
(dvoid*)*pszResult,
(sb4)256, SQLT_STR,
(dvoid*)m_pIndicator1,
(ub2*)0, (ub2*)0, (ub4)OCI_DEFAULT);
m_pIndicator2 = malloc(sizeof(OCIInd));
m_pDefine2 = NULL;
OCIDescriptorAlloc(m_OCIEnvironment, &blob, (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0);
OCIDefineByPos(m_OCIStatement, &m_pDefine2,
m_OCIError, (ub4)2,
(dvoid*)blob,
(sb4)-1, SQLT_BLOB,
(dvoid*)m_pIndicator2,
(ub2*)0, (ub2*)0, (ub4)OCI_DEFAULT));
iStatus = OCIStmtExecute(m_OCISrvCtx, m_OCIStatement, m_OCIError, (ub4)1, (ub4)0,
(OCISnapshot *)NULL, (OCISnapshot *)NULL,
(ub4)OCI_DEFAULT);
// results:
// iStatus = -1;
// Errorstring: ORA-01008: not all variables bound
}
You don't have any OCIBindByName() calls. OCIDefineByPos() is used when running SQL queries, which you aren't.
It's odd that you use a mixture of %s and bind variables in the PL/SQL call. I think you want to use bind variables for all parameters.
One handy hint is to see how ODPI-C uses OCI. For LOBs you can get either locators or data directly. The latter is a lot faster, but limited to 1G. It's arguably easiest to install Python and cx_Oracle, and run some samples e.g. ReturnLobsAsStrings.py. You can trace the OCI calls in dpiOci.c.
There are some sample OCI programs (sadly not so accessible - your DBA may be able to install them), look out for cdemolb.c and cdemolbs.c
Best Oracle-users,
Still have problems with getting a blob from Oracle. I use it so less.
Most of the time I copy some code and a new query is working fine.
I asked my collegue to change the function.
New the query is:
select ngm_transactie_pck.get_checkout_blob('20','200') from dual
the result of this function is a blob.
So i programmed:
static OCILobLocator *blob = NULL;
after OCIHandleAlloc() and OCIStmtPrepare() as in previous example i have:
OCIDescriptorAlloc(m_OCIEnvironment, &blob, (ub4)OCI_DTYPE_LOB, (size_t)0, (dvoid **)0);
CIDefineByPos(m_OCIStatement, &m_pDefine2,
m_OCIError, (ub4)1,
(dvoid*)&blob,
(sb4)-1, OCI_DTYPE_LOB,
(dvoid*)m_pIndicator2,
(ub2*)0, (ub2*)0, (ub4)OCI_DEFAULT));
The call to OciDefineByPos() gives crash/stackoverflow.
What do I wrong?
Greetz,
Kees

lua return string c++

There is a function on Lua:
STRING getClassesList()
It returns string as it is to get on c++:
This does not work:
Const char * ClassesStr;
Lua_getglobal (L, "getClassesList");
Lua_pcall (L, 1, 1, 0);
ClassesStr = lua_tostring (L, 1);
stack: 'readQuikAgent' 'attempt to call a table value'
The function is designed to obtain a list of class codes sent from the server during the communication session. The class codes in the list are separated by a comma ",". At the end of the received line, the symbol "," is always appended.
Call format:
STRING getClassesList ()
Example:
List = getClassesList ()
As a result of the above line of code, the list variable contains a string of the form:
OPTEXP, USDRUB, PSOPT, PSFUT, SPBFUT
'attempt to call table value' means that the item at the top of the lua stack is a table not a function.
So the result of the getglobal was a table, and that can not be called.
It works (thank you siffiejoe):
lua_pcall(L, 0, 1, 0);
ClassesStr = lua_tostring(L, -1);

C++ SQLite3 prepared delete statement not working

I have a C++ application which loops through a SQLite3 database. Each row contains an ID which is checked against a vector. If the ID in the DB is not present in the vector, it should be deleted with a prepared statement. I use the following code, however the ID's won't get deleted. I Neither can get an error message from the sqlite3_step(stmt2) function.
//SETTINGS["Reference"] CONTAINS THE REFERENCE FOR THE ID's (IT's 1 FOR UNDERNEATH EXAMPLE)
vector<int> IDs; //THIS VECTOR CONTAINS THE ID's IN MY APPLICATION
rc = sqlite3_prepare_v2(db, "SELECT ID FROM Files WHERE Reference=?", -1, &stmt, 0);
sqlite3_bind_text(stmt, 1, Settings["Reference"].c_str(), Settings["Reference"].length(), 0);
CheckDBError(rc);
rc = sqlite3_step(stmt);
sqlite3_stmt* stmt2;
int rc2 = sqlite3_prepare_v2(db, "DELETE FROM Files WHERE ID=? AND Reference=?", -1, &stmt2, 0);
CheckDBError(rc2);
while(rc == SQLITE_ROW) {
string IDToCheck = NumberToString(sqlite3_column_int64(stmt, 0));
if (std::find(IDs.begin(), IDs.end(), IDToCheck) == IDs.end()) { //VERIFY AGAINST VECTOR WORKS AS EXPECTED
//I GET HERE WITH ALL MY ID's I HAVE CHECKED THAT ALREADY :)
sqlite3_bind_text(stmt2, 1, IDToCheck.c_str(), IDToCheck.length(), 0);
sqlite3_bind_text(stmt2, 2, Settings["Reference"].c_str(), Settings["Reference"].length(), 0);
rc2 = sqlite3_step(stmt2);
//CAN'T GET ANY ERROR MESSAGE (SO QUERY IS FINE, WHICH SEEMS LIKE IT?)
}
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
sqlite3_finalize(stmt2);
You must not call the finalize function before the while block, because that way you finalize your statement before using it. As per SQLite documentation (emphasis mine):
It is a grievous error for the application to try to use a prepared
statement after it has been finalized. Any use of a prepared statement
after it has been finalized can result in undefined and undesirable
behavior such as segfaults and heap corruption.

Instantiating Lua objects through the C API

I am trying to do some OO functionality in Lua via the C API. In my Lua script I have the following:
Parser = {}
Parser.__index = Parser
function Parser:create(url)
local self = {}
print ("creating")
self.baseUrl = url
setmetatable(self, Parser)
return self
end
function Parser:Foo()
print ("baseUrl: " .. self.baseUrl)
end
p = Parser:create("http://www.google.com")
p:Foo()
If I run this from the command line, it works fine and I see the following output:
creating
baseUrl: http://www.google.com
Now, if I comment out the last two lines and try the following through the C API
// <load the state and lua file>
lua_getglobal(L, "Parser");
lua_getfield(L, -1, "create");
lua_pushstring(L, "http://www.google.com");
if (lua_pcall(L, 1, 1, 0) != 0)
{
// handle error
}
This works. I see "creating" in my standard output as expected. As I understand it, the new Parser object is now on top of the stack. If I them immediately try the following:
lua_getfield(L, -1, "Foo");
if (lua_pcall(L, 0, 0, 0) != 0)
{
logger()->error("-- %1", lua_tostring(L, -1));
}
I get the following error: attempt to index local 'self' (a nil value)
Can anyone tell me what I'm doing wrong and how to get the function to run as expected?
Thank you!
The definition function Parser:Foo() ... end is equivalent to:
Parser.Foo = function(self)
print ("baseUrl: " .. self.baseUrl)
end
That is -- Foo is a function that takes one argument. When you call lua_pcall(L, 0, 0, 0) you are passing 0 arguments. Change it to lua_pcall(L, 1, 0, 0) and everything should work. (You will have to also change the pcall to create to correctly pass 2 arguments rather than 1).

OCIDefineByPos() with OCINumbers

I'm developing C++ application with OCI. I need to fetch data from the DB in to OCINumber. I'm confused on how to use the function OCIDefineByPos() with OCINumbers.
Can someone help me with this.
Given below is the part of the code where I call OCIDefineByPos function.
pStmt is a OCIStmt* and p_Error is OCIError*. Following function pointers are used.
1. pf_OCINumberFromReal = function pointer to OCINumberFromReal
2. pf_OCINumberToReal = function pointer to OCINumberToReal
3. pf_DefineByPos = function pointer to OCIDefineByPos.
OCINumber ocinTest;
long double dnum = 0.0;
(*pf_OCINumberFromReal)(p_Error, &dnum, sizeof(dnum), &ocinTest);
int iLength1 = sizeof(ocinTest);
OCIDefine* pDfn = NULL;
iRet = (*pf_DefineByPos)(pStmt, &pDfn, p_Error, 1, (dvoid *) &ocinTest,
(sword) iLength1, SQLT_NUM, (dvoid *) 0, (ub2 *)0,
(ub2 *)0, OCI_DEFAULT);
if (iRet == OCI_SUCCESS)
{
(*pf_OCINumberToReal)(p_Error, &ocinTest, sizeof(dnum), &dnum);
std::cout <<std::fixed << std::setprecision (10) << dnum << std::endl;
}
although iRet = OCI_SUCCESS it didn't fetch the value in the db correctly.(Value of the sql query defined using pStmt). dnum is 0.0 even after the call. This pf_DefineByPos is working fine for other data types such as int ,double etc.
So can someone help me to find the issue with this.
If your code is not completely taken out of context, then your missing several essential pieces.
A typical OCI program involves the following steps:
Prepare an SQL statement (OCIStmtPrepare)
Bind the result columns or output parameters to the variables that will receive the result values (OCIDefineByPos)
Execute the statement (OCIStmtExecute)
Do something with the result
It seems to me that you're skipping step 3 and expect some result right after step 2. But step 2 doesn't fetch any data. It just creates an association between the query result and your variables.
You need to DefineByPos for OCINumber with SQLT_VNU type rather than SQLT_NUM.