My sqlite3 SELECT query fails if the query contains any Unicode characters. ie, the below query returns 0 instead of the actual count. I am generating the select query using C++/Visual Studio 2010.
SELECT COUNT() FROM mytable where path = "C:\\sølvgut.txt";
When I execute the above query using SQLite Expert editor it working as expected. But in my code I am using a wrapper class CppSQLite3.cpp to execute the query which is causing the issue. In the below code, it getting inside the code else if (nRet == SQLITE_ROW)
CppSQLite3Query CppSQLite3DB::execQuery(const char* szSQL)
{
checkDB();
sqlite3_stmt* pVM = compile(szSQL);
int nRet = sqlite3_step(pVM);
if (nRet == SQLITE_DONE)
{
// no rows
return CppSQLite3Query(mpDB, pVM, true/*eof*/);
}
else if (nRet == SQLITE_ROW)
{
// at least 1 row
return CppSQLite3Query(mpDB, pVM, false/*eof*/);
}
else
{
nRet = sqlite3_finalize(pVM);
const char* szError= sqlite3_errmsg(mpDB);
throw CppSQLite3Exception(nRet, (char*)szError, DONT_DELETE_MSG);
}
}
Related
I'm new to Pro-C and Oracle (but not databases) so I probably need some fundamental help on what I'm doing wrong. I wrote the following Pro*C program to query for all the tables owned by a specific user:
#include <stdio.h>
EXEC SQL INCLUDE SQLCA;
int main() {
int i;
char oraCreds[10] = "user/pass";
char tables[50][50], parts[50][50];
exec sql connect :oraCreds;
if (sqlca.sqlcode != 0) {
printf("ERROR abbreviated\n");
return(0);
}
EXEC SQL SELECT TABLE_NAME
INTO :tables
FROM USER_TABLES;
if (sqlca.sqlcode != 0) {
printf("ERROR: Could not query database for user tables\n");
printf("\tError Code: %d\n", sqlca.sqlcode);
printf("\t%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
} else {
for (i = 0; i < 50; i++) {
printf("\nTable %d: %s\n", i+1, tables[i]);
}
}
// Code below inserted here
return(0);
}
This produces the following error:
ERROR: Could not query database for user tables
Error Code: 1403
ORA-01403: no data found
The problem is that there are records in user_tables and in sqlplus I can do a typical SELECT TABLE_NAME FROM USER_TABLES; in order to verify that.
In an attempt to verify some of the basic functionality of above program, I inserted the following query at the comment.
EXEC SQL SELECT NAME, PART_NO
INTO :tables, :parts
FROM ITEMS;
if (sqlca.sqlcode != 0) {
printf("ERROR: Could not query database for user tables\n");
printf("\tError Code: %d\n", sqlca.sqlcode);
printf("\t%.*s\n", sqlca.sqlerrm.sqlerrml, sqlca.sqlerrm.sqlerrmc);
} else {
for (i = 0; i < 50; i++) {
printf("\nTable %d: %s\n", i+1, tables[i]);
}
}
This second query gives the expected results and prints out one line for each item's name.
If I understand correctly, the table, user_tables, is a standard part of Oracle, so is there something special about it that would be throwing off my query? I've started reading some alternate ways to query for the user's tables, but I would love to know why the above method does not work.
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 following program tries to insert a new row and a new column to an already existing database with a table "people" containing four cols (id, lastname, firstname, phonenumber). While the row gets inserted successfully, the column is not getting added.
#include <stdio.h>
#include <stdlib.h>
#include <libpq-fe.h>
#include <string.h>
int main()
{
PGconn *conn;
PGresult *res;
int rec_count;
int row;
int col;
conn = PQconnectdb("dbname=test host=localhost user=abc1 password=xyz1");
if(PQstatus(conn) == CONNECTION_BAD) {
puts("We were unable to connect to the database");
exit(0);
}
res = PQexec(conn,"INSERT INTO people VALUES (5, 'XXX', 'YYY', '7633839276');");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed1: %s", PQerrorMessage(conn));
PQclear(res);
}
else
printf("Successfully inserted value in Table..... \n");
res = PQexec(conn,"update people set phonenumber=\'5055559999\' where id=3");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed2: %s", PQerrorMessage(conn));
PQclear(res);
}
res = PQexec(conn, "ALTER TABLE people ADD comment VARCHAR(100) DEFAULT 'TRUE'");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed3: %s", PQerrorMessage(conn));
PQclear(res);
}
rec_count = PQntuples(res);
printf("We received %d records.\n", rec_count);
puts("==========================");
for(row=0; row<rec_count; row++) {
for(col=0; col<3; col++) {
printf("%s\t", PQgetvalue(res, row, col));
}
puts("");
}
puts("==========================");
PQclear(res);
PQfinish(conn);
return 0;
}
The program after being compiled and linked gives the following output:
$ ./test
Successfully inserted value in Table.....
We received 0 records.
==========================
==========================
In the postgresql environment, the table "people" is updated with an extra row and a column containing "TRUE".
This is my first program with C embedded with postgresql. Please help!!
This line:
res = PQexec(conn, "EXEC('UPDATE people SET comment = ''TRUE'';');");
should be:
res = PQexec(conn, "UPDATE people SET comment = 'TRUE'");
The EXEC syntax is part of embedded SQL in C with ECPG. It's not to be combined with PQexec from the C libpq library, which is clearly what you're using given the rest of the source code.
Also the result of an UPDATE with no RETURNING clause has PQresultStatus(res)==PGRES_COMMAND_OK, not PGRES_TUPLES_OK
PGRES_COMMAND_OK
Successful completion of a command returning no data.
See Command Execution Functions
You also want to test any PGresult returned by PQexec, not only the result of your last query, because any query may fail.
How can you retrieve data without doing a SELECT statement ?
Never used PQexec, but i guess the code to add might be like this:
res = PQexec(conn, "ALTER TABLE people ADD comment VARCHAR(100) DEFAULT 'TRUE'");
if(PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "Insertion Failed3: %s", PQerrorMessage(conn));
PQclear(res);
}
//Add PQexec and select statement here.
//Something "like" this.
res = PQexec(conn, "SELECT * FROM people;");
if(PQresultStatus(res) != PGRES_TUPLES_OK) {
fprintf(stderr, "Select Failed: %s", PQerrorMessage(conn));
PQclear(res);
}
rec_count = PQntuples(res);
printf("We received %d records.\n", rec_count);
I like to log the compiled Statement after this:
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
sqlite3_bind_int( compiledStatement, 1, updateThis.web_id);
[...]
}
NSLog(#"Put out the complete SQLite Statement.");
The direct output failed, and i think this is not the way to do it:
NSLog(#"%#",compiledStatement);
You can't print the compiledStatement. What you can do is implement the sqlite3_trace callback function. This will print every executed sql statement.
To implement the function add this before your #implementation block
void sqliteCallbackFunc(void *foo, const char* statement) {
NSLog(#"=> %s", statement);
}
This is the function you will point to.
To point to this function simple call:
sqlite3_trace(db, sqliteCallbackFunc, NULL);
void max_min(sqlite3 *db)
{
//call back*********
int i, ncols;
sqlite3_stmt *stmt;
char *sql;
const char *tail;
char *zErrMsg = 0;
int rc;
//******************
//min/max variables
char min[20];
char max[20];
//we want only the min and max value of this table
sql = "SELECT MIN(Start),MAX(End)FROM GMTI;"; //doesn't extract but works in GUI tool?
//sql = "SELECT * FROM GMTI WHERE Start<16;"; //works?
rc = sqlite3_prepare(db, sql, strlen(sql), &stmt, &tail);
if(rc != SQLITE_OK){
fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
}
rc = sqlite3_step(stmt);
ncols = sqlite3_column_count(stmt);
printf("Number of columns: %d and row status: %d", ncols, rc);
while(rc == SQLITE_ROW){
for(i=0; i<ncols; i++){
if (strncmp("Start", sqlite3_column_name(stmt,i), strlen("Start")) == 0)
{
strncpy(min, sqlite3_column_text(stmt,i), strlen(sqlite3_column_text(stmt,i)));
strcpy(min + strlen(sqlite3_column_text(stmt,i)), "\0");
printf("min is: %s\n", min);
printf("<br>");
}
if (strncmp("End", sqlite3_column_name(stmt,i), strlen("End")) == 0)
{
strncpy(max, sqlite3_column_text(stmt,i), strlen(sqlite3_column_text(stmt,i)));
strcpy(max + strlen(sqlite3_column_text(stmt,i)), "\0");
printf("max: %s\n", max);
printf("<br>");
}
}//end for
fprintf(stderr, "\n");
rc = sqlite3_step(stmt);
}//end while
sqlite3_finalize(stmt);
}
When I use the sql query above with the MIN and MAX functions, nothing prints out for min and max. If I use one of the other statements commented out there, it works as expected, printing the selected query.
What is different about the max and min in the query, that it can't extract the values? Is it not in table format?
Also, I tested the problem query string in an SqLite database browser on the same database and it works, displaying the two - min and max values.
Any suggestions would be greatly appreciated.
Thanks.
Try printing out the returned column names. Maybe they don't equal "Start" and "End" as you assumed?
Maybe you should add a space between MAX(End) and FROM ?