You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A statement can be prepared once and executed as many times as needed (see Binding variables section)
Unfortunately that's exactly what's not working. At the second OCI_Execute() it hangs and has to be killed by force. While it hangs the cpu load is constantly 100% for the core which is running it.
I'm using ocilib 4.7.6 with the 64bit oracle 12.1 instant client libs on osx. Here is my test program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <ocilib.h>
using namespace std;
int main() {
OCI_Connection* cn;
OCI_Statement* st;
OCI_Date *date;
OCI_Lob *lob;
string tmp;
OCI_Initialize(NULL, NULL, OCI_ENV_CONTEXT);
cn = OCI_ConnectionCreate("1.2.3.4:1521/DB", "xxx", "xxx", OCI_SESSION_DEFAULT);
if (!cn) {
perror(OCI_ErrorGetString(OCI_GetLastError()));
exit(1);
}
st = OCI_StatementCreate(cn);
OCI_ExecuteStmt(st, "ALTER SESSION SET current_schema = xxx, NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'");
OCI_Prepare(st, "insert into tester (clobber, date_) values(:bclob, :bdate)");
// first run
date = OCI_DateCreate(NULL);
OCI_DateFromText(date, "2016-04-13 20:38:14", "YYYY-MM-DD HH24:MI:SS");
OCI_BindDate(st, ":bdate", date);
lob = OCI_LobCreate(cn, OCI_CLOB);
tmp = "clob 1 is cool";
OCI_LobWrite(lob, &tmp[0], tmp.length());
OCI_BindLob(st, ":bclob", lob);
OCI_Execute(st);
OCI_DateFree(date);
OCI_LobFree(lob);
// second run
date = OCI_DateCreate(NULL);
OCI_DateFromText(date, "2016-04-14 20:38:14", "YYYY-MM-DD HH24:MI:SS");
OCI_BindDate(st, ":bdate", date);
lob = OCI_LobCreate(cn, OCI_CLOB);
tmp = "clob 2 is cooler";
OCI_LobWrite(lob, &tmp[0], tmp.length());
OCI_BindLob(st, ":bclob", lob);
OCI_Execute(st); // <= hangs here!
OCI_DateFree(date);
OCI_LobFree(lob);
OCI_Commit(cn);
OCI_StatementFree(st);
OCI_ConnectionFree(cn);
OCI_Cleanup();
exit(0);
}
This is a misuse of the API.
Host bind variables must remain valid during the lifetime of the prepared statement.
In your code you are deleting these variables while still being bounded to the statement.
As you did not set the option to allow rebinding variables, second binding calls fail and the statement still uses previously bounded and destroyed host variables leading accessing dandling pointers and thus undefined behaviour.
The concept of bind variables is to bind them once and reuse them across executions. You just need to update their content.
Oh I see, the binding is still part of the prepare stage so to say. Well, that works with one exception: I have to use OCI_LobTruncate() for every consecutive run because OCI_LobWrite() appends the text otherwise.
In practice however, at least for things like number and varchar, using OCI_AllowRebinding() is much better because declaring all variables in advance (the insert values are often generated within loops) is usually not possible or would require to copy the content to the already bound variables every time. The latter is the case for lob or date anyway so for them it doesn't matter.
Thanks for the reply and sorry for the false bugreport.
Hi,
a note in api.h says:
Unfortunately that's exactly what's not working. At the second OCI_Execute() it hangs and has to be killed by force. While it hangs the cpu load is constantly 100% for the core which is running it.
I'm using ocilib 4.7.6 with the 64bit oracle 12.1 instant client libs on osx. Here is my test program:
and the debugger output:
The text was updated successfully, but these errors were encountered: