Call SQL function without creating tables/database - iphone

Function HEX is one of the core functions in sqlite
I would like to call the function from my objective-c code without actually creating a database in my app .. and so on.
What would be the simplest way to call the function with the least addition of classes?
I found lots of functions written in o-c that HEX a string. However, they are not correct as they produce results different from the HEX function of mysql.
Solution: Converting a string to its Hex value
+(NSString *) stringToHex:(NSString *)str
{
NSString *aResult;
sqlite3 *database;
if(sqlite3_open(":memory:", &database) == SQLITE_OK)
{
NSString *sqlStatement = [NSString stringWithFormat:#"select HEX('%#')",str];
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, [sqlStatement cStringUsingEncoding:NSUTF8StringEncoding], -1, &compiledStatement, NULL) == SQLITE_OK) {
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
aResult = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)];
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
return aResult;
}

You can open an in-memory db using sqlite3_open and use that. To do this, open a db with the file name :memory: (w/ the colons).
If you only want the hex function, you can also look into the source code of SQLite. It's plain C and in the public domain.

You can easely retrieve HEX string from a NSDate instance:
NSString *tokenKey = [[[deviceToken description] stringByTrimmingCharactersInSet:
[NSCharacterSet characterSetWithCharactersInString:#"<>"]]
stringByReplacingOccurrencesOfString:#" " withString:#""];

Sounds like you just want to convert an NSString to hex. You could search on here for a better solution, or here's one I just contrived:
+ (NSString *)stringToHex:(NSString *)string
{
NSUInteger hexLength = ([string length] * 2) + 1;
char *hex = (char *)malloc(sizeof(char) * hexLength);
if (hex == NULL)
return (#"");
const char *cString = [string cStringUsingEncoding:NSASCIIStringEncoding];
for (NSUInteger len = 0, pos = 0; len < [string length]; len++, pos += 2)
snprintf(hex + pos, 3, "%2x", cString[len]);
hex[hexLength] = '\0';
NSString *hexString = [NSString stringWithCString:hex encoding:NSASCIIStringEncoding];
if (hex != NULL)
free(hex);
return (hexString);
}

Related

not getting inside while loop when selecting a single row from sqlite

I have a problem with sqlite, when i select a single row from table and then check sqlite3_step(statement) == SQLITE_ROW both values are different and not getting inside while statement.
This is the code:
if (sqlite3_prepare_v2(db, query_stmt, -1, &statement, NULL) == SQLITE_OK)
{
//NSLog(#"working777.............%d",sqlite3_step(statement));
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSLog(#"working888.............%d",SQLITE_ROW);
NSString *addressField = [[NSString alloc] initWithUTF8String: (const char *) sqlite3_column_text(statement, 0)];
NSString *phoneField = [[NSString alloc] initWithUTF8String:(const char *)sqlite3_column_text(statement, 1)];
NSLog(#"............statement...........addressField %#, phoneField %#",addressField,phoneField);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
The proper way to create such a query would be like this:
NSString *querySQL = #"SELECT * FROM Major_Events WHERE temple_id = ?";
Then prepare the statement. I assume query_stmt is the char * value from querySQL.
Once the statement is prepared you then need to bind the value.
sqlite3_bind_int(statement, 1, temp_id); // bind is 1-based
Of course temp_id needs to be an int value and not a string. There are various sqlite3_bind_xxx statements for different data types. Use the appropriate one.
Once all of the query parameters are bound, you can execute the query using sqlite3_step.
The nice thing about this approach over string formats is that strings get properly escape and put in quotes for you. It's much harder to mess up and it makes your queries much safer against SQL injection attacks.
For many records:-
if (sqlite3_open([[self getDBPath] UTF8String], &database) == SQLITE_OK) {
const char *sql = "select * from Place";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
}
sqlite3_finalize(selectstmt);
sqlite3_close(database);
}
}
else
{
sqlite3_close(database);
}
If you want a single record then change while to if
if(sqlite3_step(selectstmt) == SQLITE_ROW) {
rest everything will be same
I hope it helps and if your while loop is not getting executed then it means there is some problem with your query.You need to check that also.

How to add nsmutable array into sqlite database table

How to add nsmutablearray into the sqlite database table?Can any one help me to code?
You can use :
for (int i = 0; i < [mutArray count]; i++)
{
NSString *string = [mutArray objectAtIndex:i];
// insert query
insert into table_name ('string') values(column_name);
}
Use looping Controls to sort the array and insert each values
Example:
for(int itemIndex = 0; itemIndex < [yourArray count];itemIndex++){
NSString *myname = [yourArray objectAtIndex:itemIndex];
//insert myname to database.
}
To retrieve, you can use the sample below code
if(sqlite3_open([path UTF8String], &dataBase) == SQLITE_OK)
{
NSString *query = [NSString stringWithFormat:#"select name from syncTable where Crc = %d",crc]; const char *sql = [query UTF8String];
sqlite3_stmt *statement;
if (sqlite3_prepare(dataBase, sql, -1, &statement, NULL) == SQLITE_OK)
{
char *name;
unsigned int value;
while(sqlite3_step(statement) == SQLITE_ROW)
{
name = (char *)sqlite3_column_text(statement, 0);
[yourArray addObject:[NSString stringWithUTF8String:name]];
}
sqlite3_finalize(statement);
}
}
Here is a list of tutorials for using sqlite with iphone. Its not a matter of simulator or device. It will work fine with simulator also.
Create your db structure properly and work based on this tutorials.
Or
I'd recommend you to use Core Data if you want you work with databases on iPhone OS.
This tutorial should match your app quite well.
Please ask if any more questions.

iOS SQLite Sum and retrieve data

I have a SQLite database that I am creating in my iOS application. A series of numbers are being stored in this database. I want to sum the entire column, and return the data to be displayed within the application.
Everything writing to the DB is working properly, but I am stuck trying to return the summed data. Any help would be greatly appreciated.
-(void) dataReturn: (NSString *) tableNamed{
NSString *myData = [NSString stringWithFormat:#"SELECT SUM(column1) AS data1 FROM myDB", tableNamed];
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(db, [myData UTF8String], -1, &statement, nil) ==SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW){
int *field2 = (int *) sqlite3_column_int(statement, 1);
NSString *myString =[[NSString alloc] initWithFormat:#"%#", field2];
}
}
}
Hello Nathan making a call as
[self dataReturn:#"Bill"];
to function
-(void)dataReturn:(NSString *)tableName{
sqlite3 *database;
sqlite3_stmt *statement;
NSString *queryString = [NSString stringWithFormat:#"SELECT SUM(price) AS TOTAL FROM %#", tableName];
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
if(sqlite3_prepare_v2(database, [queryString UTF8String], -1, &statement, nil) == SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW) {
int field1 = sqlite3_column_int(statement, 0);
NSLog(#"The sum is %d ", field1);
}
}
}
}
will Fetch you desired data. The schema for Table "Bill" is "CREATE TABLE Bill (price double,quantity INTEGER)". The result fetched will have columns indexed from "0" so we pass 0 for first column. Hope you can take some hint from it. Cheers!!
int field1 = sqlite3_column_int(statement, 0);
From the sqlite3_column_int docs:
The leftmost column of the result set has the index 0.
Additionally, that function returns an int, not an int*. Try:
int field2 = sqlite3_column_int(statement, 0);

BAD_ACCESS on SQLITE selection

I am getting EXC_BAD_ACCESS when I attempt to do anything with the value I'm selecting from the local SQLITE database on an iPhone development. The code for my function is
-(void) updateFromDB {
// Setup the database object
sqlite3 *database;
// Open DB
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
NSString *query = [NSString stringWithFormat:#"SELECT MOD_ID FROM MODULE;"];
//NSLog(#"QUERY: %#",query);
// Prepare statement
sqlite3_stmt *statement;
if(sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, NULL) == SQLITE_OK) {
// Execute SQL
while (sqlite3_step(statement) == SQLITE_ROW) {
// Get MOD_IDs
NSInteger MOD_ID = sqlite3_column_int(statement, 0);
NSString *ID = [NSString stringWithFormat:#"%#",MOD_ID];
//=======================
// Get Notice Module Data
//=======================
if (MOD_ID == 1) {
self.noticeModule = [[ModuleSetting alloc] initWithID:ID];
}
}
} else {
NSAssert1(0,#"Error: failed to prepare statement. '%s'", sqlite3_errmsg(database));
}
// Release the compiled statement from memory
sqlite3_finalize(statement);
} else {
sqlite3_close(database);
NSAssert1(0,#"Failed to open database. '%s'",sqlite3_errmsg(database));
}
sqlite3_close(database);
}
The bad access occurs on the line
NSString *ID = [NSString stringWithFormat:#"%#",MOD_ID];
Thanks for any help you can offer!
%# denotes objects. But MOD_ID seems to be an integer. So your format should be %d,
NSString *ID = [NSString stringWithFormat:#"%d", MOD_ID];
You can't use %# in format strings for integers, only for Obj-C objects. For integers, use %d (or for NSInteger, I think it is recommended to use %ld).
Have a look at the String Format Specifiers guide.
MOD_ID is not a pointer, so %# isn't correct.
Use below
NSInteger MOD_ID = sqlite3_column_int(statement, 0);
NSString *ID = [NSString stringWithFormat:#"%d",MOD_ID];

iphone sqlite query crashes if no rows returned

I have the following function in my iPhone project which works great...unless the query returns nothing and then the app crashes. It is being a pain to debug with none of the breakpoints being activated at all!
I know this works as I pass in static stuff that is in the DB and it returns a value.
-(NSString *)getSomeText:(NSString *)toPass {
sqlite3 *database;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:#"sf.sqlite"];
int strLength = 0;
strLength = [toPass length];
if (strLength <3)
return #"Unknown";
NSString *MIDstr;
NSMutableString * toPass Copy = [NSMutableString stringWithString:toPass];
MIDstr = [toPassCopy substringWithRange:NSMakeRange(0, 3)];
// Open the database from the users filessytem
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {
// Setup the SQL Statement and compile it for faster access
NSString *BaseSQL = [NSString stringWithFormat:#"select * from MIDS where MID = '%#'",MIDstr];
NSLog(BaseSQL);
const char *sqlStatement = [BaseSQL UTF8String];
//NSLog(BaseSQL);
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
// Loop through the results and add them to the feeds array
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
NSString *aName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)];
NSString *returnString = [NSString stringWithFormat:#"%#",aName];
return returnString;
}
}
// Release the compiled statement from memory
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}
A. if sqlite3_step does not return any rows, you crash because you have declared that you are returning a NSString, but when there are no rows you return nothing.
The caller will try to read a NSString from the stack and thus end up dereferencing garbage.
To quickly fix the problem, write:
sqlite3_close(database);
return nil;
}
and make sure the caller handles nil results.
B/ If you do have data, your code never gets to call sqlite3_finalize and sqlite3_close because you return early:
while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
[..]
return returnString;
while (sqlite3_step(sqlstatement) == SQLITE_ROW )
{
//Your code goes here
}
sqlite3_finalize(sqlstatement);
sqlite3_close(databaseRefObj);
close the database and finalize your statement after the while loop this helped me out,