I get an error of invalid Handle when OCIStmtFetch2 function executes in my code.
char *query = "SELECT id FROM id_table WHERE ROWNUM <= :1";
rc = OCIStmtPrepare(stmt, errhp, (OraText*)query, strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT);
OCIBind *bindp = NULL;
sb2 pos = 1;
int key=13;
rc = OCIBindByPos(stmt, &bindp, errhp, 1, &key, sizeof(int), SQLT_INT, (dvoid*)&pos, NULL, NULL, 0, NULL, OCI_DEFAULT);
char output[key][120];
sb2 output_ind[1];
ub2 output_len[1];
ub2 output_code[1];
OCIDefine *defnpp;
rc = OCIDefineByPos(stmt, &defnpp, errhp, 1, (dvoid*)output, 120, SQLT_STR, (dvoid*)output_ind, output_len, output_code, OCI_DEFAULT);
int rows = key;
/* execute */
rc = OCIStmtExecute(svchp, stmt, errhp, key, 0, NULL, NULL, OCI_DEFAULT);
rc = OCIStmtFetch2(stmt, errhp, 0, OCI_DEFAULT, 0, OCI_DEFAULT);
If I bind the placehoder :1 with integer value 12 then the code works, any value greater than 12 gives me Error OCI_INVALID_HANDLE error after running OCIStmtFetch2. I have the following code to catch error, which I run after each OCI functions mentioned in the code above
if (rc != OCI_SUCCESS && rc != OCI_SUCCESS_WITH_INFO) {
report_error(checkerr("Function Name()", errhp, rc));
return 1;
}
Can anyone please help me what is incorrect in my code? Thank you!
It's not working for any value greater than 12 because you are defining your output array to be char output[13][120]. I think you already got the idea from Joachim's comment that your output buffer is insufficient for more rows.
I'll try to answer your follow-up question about ind, rlen and rcode variables in the function call -
rc = OCIDefineByPos(stmt, &defnpp, errhp, 1, (dvoid*)output, 120, SQLT_STR, (dvoid*)output_ind, output_len, output_code, OCI_DEFAULT);
OCIDefineByPos associates an item in a select list with the type and output data buffer.
output_ind here is a pointer to an indicator array. Each bind and define OCI call has a parameter that associates an indicator variable, or an array of indicator variables, with a DML statement, a PL/SQL statement, or a query. Here you can know more about indicator variables and their usage.
output_len here is a pointer to array of length of data fetched.
output_code here is pointer to array of column-level return codes.
Related
Good afternoon,
I've got this code below:
double bd_sacar_imc(double altura, double peso) {
sqlite3 *db;
char *zErrMsg = 0;
int rc;
char *sql = ("SELECT %lf/(%lf * %lf);", peso, altura, altura);
rc = sqlite3_exec(db, sql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
return 0;
} else {
fprintf(stdout, "Consulta creada con exito\n");
return peso / (altura * altura);
}};
However, I get this error:
..\BD\bd.c:170:14: error: incompatible types when initializing type 'char *' using type 'double' char *sql = ("SELECT %lf /( %lf * %lf);", peso, altura, altura);
What might be happening?
It looks like you are trying to build a string. For that you can use snprintf.
char sql[64];
int size = snprintf(sql, 64, "SELECT %lf/(%lf * %lf);", peso, altura, altura);
Note that I kept the return value. This is to handle any future error where you modify a statement in a way that might result in buffer overflow or other error. You can probably just deal with this by using a debug assertion, as this pre-sized string should be large enough to hold the intended SQL.
if (size < 0 || size >= 64) {
assert(0);
return 0;
}
However, since you are using sqlite library, you should instead use the proper methods to prepare a statement and bind values to it, rather than inserting the values into the string yourself.
I am using libssh.
After calling ssh_channel_write, I have to know whether there has data to read. (But I don't want to retrieve data.)
If there has no data to read (for example, after 10s), I will call ssh_channel_write again.
Both of ssh_channel_read and ssh_channel_read_nonblocking cannot do this. (And checking ssh_get_status with SSH_READ_PENDING also does not work.)
Is there any ways to solve this problem?
It's NonBlocking ...
Use the ssh_select() function. It works quite similar to the regular select(), but uses channels instead of sockets.
int ssh_select (ssh_channel *channels, ssh_channel *outchannels,
socket_t maxfd, fd_set *readfds, struct timeval *timeout);
For instance, a single channel implementation:
ssh_channel channels[2];
ssh_channel myChannel = ssh_channel_new (ssh_session session);
channels[0] = myChannel;
channels[1] = NULL;
struct timeval timeout = (0, 200000); // 0 seconds, 200 millis
int rc = ssh_select (channels, NULL, NULL, NULL, &timeout);
if (rc > 0) {// There is a pending data.
if (rc < 0) // the ssh_select() error.
if (rc == 0) // You've got a broken connection.
I'd like to run the SQL query: SELECT COUNT(id) AS nbr FROM user WHERE name LIKE '%John%', and get the number of records matched by the keyword John.
So I've written the following code :
unsigned int nbr;
char *sql, *like;
sqlite3 *db;
sqlite3_stmt *stmt;
/* Database connection etc. */
like = _make_string("%%%s%%", keyword); /* keyword: John */
printf("Like clause: %s\n", like);
sql = _make_string("SELECT COUNT(id) AS nbr FROM user WHERE name LIKE ?");
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
sqlite3_bind_text(stmt, 1, like, -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_ROW) {
/* error, SQL execution failed */
}
nbr = sqlite3_column_int64(stmt, 1);
printf("Number of record: %u\n", nbr);
/* Free strings, finalize statement, disconnect db etc. */
For reason of simplicity, some return value tests are ignored in the snippet. _make_string(const char *fmt, ...) is a printf-like function which can form strings, and it did return %John% to me.
However, my code always returns 0 record. I have tried the SQL in sqlite3 command line shell, but it has found 2 records.
Any idea please ?
I've hard coded the LIKE clause and removed the sqlite3_bind_text function, and it doesn't change the result.
sql = _make_string("SELECT COUNT(id) AS nbr FROM client WHERE name LIKE '%John%'");
sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (sqlite3_step(stmt) != SQLITE_ROW) {
/* error */
}
nbr = sqlite3_column_int64(stmt, 1);
printf("Number of record: %u\n", nbr);
The program always returns 0 records.
Well, I've found the answer in the mailing list archive of SQLite Why bind indexes start from 1 and column indexes start from 0?
In fact, the bind index starts from 1, but the column index starts from 0. So the code should be modified as the following
nbr = sqlite3_column_int64(stmt, 0);
printf("Number of record: %u.\n", nbr);
Now the program returns 2 (records) !
The title is pretty much all the information I have because I cannot find an issue with the code. The same instance of database that is being used in the code below is able to successfully insert, delete and select, but this function does not work. No error code is retured(Always 0), and the program continues to run nominally after executing this function.
Here is the table information:
reminder (uniqueID integer primary key autoincrement, title text not null, details text, time integer)
Code in question:
- (void) updateEntryData:(ReminderData *)data
{
sqlite3_stmt *statement;
char *updateCommand = "UPDATE reminder SET title = '?', details = '?', time = ? WHERE uniqueID = ?";
int e = sqlite3_prepare_v2(database, updateCommand, -1, &statement, nil);
if(e != SQLITE_OK) {
NSLog(#"Problem with updateEntryWithUniqueID");
NSLog(#"Error Code: %d, message '%s'", e, sqlite3_errmsg(database));
return;
}
sqlite3_bind_text(statement, 1, [data.title UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_text(statement, 2, [data.details UTF8String], -1, SQLITE_TRANSIENT);
sqlite3_bind_int(statement, 3, [data.time timeIntervalSince1970]);
sqlite3_bind_int(statement, 4, data.uniqueID);
NSLog(#"\nID: %d\nTitle: %#\nDetails: %#\nTime: %#", data.uniqueID, data.title, data.details, data.time);
if(sqlite3_step(statement) != SQLITE_DONE) {
NSLog(#"Problems updating entry in reminder");
}
/* Finished */
sqlite3_finalize(statement);
}
Any help would be greatly appreciated; I am stumped.
Edit: Forgot to mention that the sql command used works when entered into the sqlite console.
Just remove the single quotes around the parameters. Wrapping the placeholders will make it a value and not a parameter anymore.
char *updateCommand = "UPDATE reminder SET title = ?, details = ? .....";
luaL_loadstring(L, "return 3, 4, 5");
int R = lua_pcall(L, 0, 3, 0);
Lua can return multiple values. But currently I have to hardcode the count of the return values. Can I know the count at runtime dynamically?
Yes.
int top = lua_gettop(L);
luaL_loadstring(L, "return 3, 4, 5");
int R = lua_pcall(L, 0, LUA_MULTRET, 0);
int nresults = lua_gettop(L) - top;
You use LUA_MULTRET, and then use lua_gettop to figure out the top of the stack before and after the call.