Is there a way to use SQLite soundex() in iOS apps?
Please guide me to find a way...
Tried Homegrew but it works on terminal and I need to run soundex everytime in terminal. Also i dont know how to port to iOS APP.
Terminal work
You can the sqlite3_create_function to create the soundex SQL function:
#import "ViewController.h"
#import <sqlite3.h>
void soundex(sqlite3_context *context, int argc, sqlite3_value **argv);
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self test];
}
- (sqlite3 *)openDatabase
{
NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path = [docsPath stringByAppendingPathComponent:#"test.db"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:path])
{
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"db"];
[fileManager copyItemAtPath:bundlePath toPath:path error:nil];
}
sqlite3 *db;
int rc;
if ((rc = sqlite3_open_v2([path UTF8String], &db, SQLITE_OPEN_READWRITE, NULL)) != SQLITE_OK)
{
NSLog(#"%s: sqlite3_open_v2 failed: %d", __FUNCTION__, rc);
}
return db;
}
- (BOOL)createFunction:(sqlite3 *)db
{
int rc;
if ((rc = sqlite3_create_function(db, "soundex", 1, SQLITE_ANY, NULL, soundex, NULL, NULL)) != SQLITE_OK)
{
NSLog(#"%s: sqlite3_create_function error: %s", __FUNCTION__, sqlite3_errmsg(db));
}
return rc;
}
- (void)test
{
int rc;
sqlite3 *db = [self openDatabase];
[self createFunction:db];
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, "SELECT name FROM todo WHERE soundex(name) = soundex('Mani')", -1, &statement, NULL) != SQLITE_OK)
{
NSLog(#"%s: sqlite3_prepare_v2 error: %s", __FUNCTION__, sqlite3_errmsg(db));
}
while ((rc = sqlite3_step(statement)) == SQLITE_ROW)
{
const unsigned char *name = sqlite3_column_text(statement, 0);
if (name)
NSLog(#"name=%s", name);
else
NSLog(#"name=NULL");
}
if (rc != SQLITE_DONE)
{
NSLog(#"%s: sqlite3_step error: %s", __FUNCTION__, sqlite3_errmsg(db));
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
#end
void soundex(sqlite3_context *context, int argc, sqlite3_value **argv)
{
const char *str = (const char*)sqlite3_value_text(argv[0]);
const char *in = str;
static int code[] =
{ 0,1,2,3,0,1,2,0,0,2,2,4,5,5,0,1,2,6,2,3,0,1,0,2,0,2 };
/* a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z */
char ch;
int last;
int count;
char key[5];
/* Set up default key, complete with trailing '0's */
strcpy(key, "Z000");
/* Advance to the first letter. If none present,
return default key */
while (*in != '\0' && !isalpha(*in))
++in;
if (*in == '\0') {
sqlite3_result_text(context, key, 4, SQLITE_TRANSIENT);
return;
}
/* Pull out the first letter, uppercase it, and
set up for main loop */
key[0] = toupper(*in);
last = code[key[0] - 'A'];
++in;
/* Scan rest of string, stop at end of string or
when the key is full */
for (count = 1; count < 4 && *in != '\0'; ++in) {
/* If non-alpha, ignore the character altogether */
if (isalpha(*in)) {
ch = tolower(*in);
/* Fold together adjacent letters sharing the same code */
if (last != code[ch - 'a']) {
last = code[ch - 'a'];
/* Ignore code==0 letters except as separators */
if (last != 0)
key[count++] = '0' + last;
}
}
}
sqlite3_result_text(context, key, 4, SQLITE_TRANSIENT);
}
You need to include the sqlite.c/sqlite.h files in your project from the sqlite amalgamation itself vs. using the libsqlite dylib.
Be sure to set the SQLITE_SOUNDEX preprocessor flag as well to include this feature when you build.
1) download and unzip the sqlite amalgamation. Add the sqlite.h/sqlite.c files to your project.
2) add SQLITE_SOUNDEX=1 to your project's Preprocessor Macros, via the Build Settings screen in XCode.
3) remove libsqlite3XXX.dylib from your project's Link With Libraries list, via the Build Phases screen in Xcode.
Related
I have a sqlite in my app , and everything seem to be ok , but i database method the while loop is not executed , and i can't get the result from query. Could somenone help me? Any help will be apreciate !
I also create a copy for databse, as i saw in other answer for other questions .
- (void)viewDidLoad {
[super viewDidLoad];
int sqlite3_open(const char *filename, sqlite3 **database);
sqlite3 *contactDB; //Declare a pointer to sqlite database structure
NSString *path = [[NSBundle mainBundle] pathForResource:#"verbeGeo" ofType:#"sqlite"];
if (sqlite3_open([path UTF8String], &contactDB) == SQLITE_OK)
{
NSLog(#"DB is open");
} else {
NSLog(#"DB can be open");
}
NSString *querySQL = #"select id from conjugare where rowid=1";
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(contactDB, query_stmt, -1,
&statement, NULL) == SQLITE_OK)
{
NSLog(#"Statement prepared successfully");
} else {
NSLog(#"Statement preparation failed");
NSLog(#"Error while creating update statement. '%s'", sqlite3_errmsg(contactDB));
NSLog(#"%s Prepare failure '%s' (%1d)", __FUNCTION__, sqlite3_errmsg(contactDB), sqlite3_errcode(contactDB));
}
sqlite3_step(statement);
sqlite3_finalize(statement);
[self database];
}
-(void)database{
sqlite3 *contactDB;
NSString *querySQL = #"select id from conjugare where rowid=1";
const char *query_stmt = [querySQL UTF8String];
sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL);
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *idNumber =
[[NSString alloc] initWithUTF8String:
(const char *) sqlite3_column_text(statement, 0)];
}
sqlite3_finalize(statement);
}
Your sqlite3_open statement is initializing the contactDB variable defined in viewDidLoad. The contactDB variable defined in database is local to that method and not initialized.
1) Either make contactDB an instance variable or pass it to database.
2) Check error returns for all calls (e.g. sqlite3_prepare_v2 in the database method).
I'm starting to develop a small iOS application just for learning, and I'm attempting to use SQLite to store my app data. I'm using a simple CRUD operations, but when I compile the app (I want to try it in the device emulator) i've got this error
I've added libsqlite3.dylib to my project dependences.
I've tried many solutions, bun no one fix my problem.
Any idea about what i'm doing wrong?
Thank you so much
ps. The code are the following:
-(int) getPushCount {
int count = 0;
const char *dbpath = [databasePath UTF8String];
if(sqlite3_open(dbpath, &database) == SQLITE_OK) {
NSString *query = [NSString stringWithFormat:#"SELECT COUNT(*) FROM recived_push WHERE read = 1"];
const char *getQuery = [query UTF8String];
if(sqlite3_prepare_v2(database, getQuery, -1, &statement, NULL) == SQLITE_OK) {
while(sqlite_step(statement) == SQLITE_ROW) {
count = sqlite_column_int(statement,0);
}
} else {
NSLog(#"Failed from sqlite3_prepare_v2.");
NSLog(#"Error is: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(statement);
sqlite3_close(database);
} else {
NSLog(#"Oops! Something went terribly wrong...");
NSLog(#"%s",sqlite3_errmsg(database));
return nil;
}
NSLog(#"**Count: %d",count);
return count;
}
change your code like this..
while (sqlite3_step(statement)== SQLITE_ROW) {
count = sqlite3_column_int(statement, 0);
}
this is what i am doing in header
static sqlite3 *database = nil;
static sqlite3_stmt *deleteStmt = nil;
#implementation SQLAppDelegate
#synthesize window;
#synthesize navigationController;
#synthesize coffeeArray;
this is what i am using for deleting raw
- (void) removeCoffee:(NSNumber *)coffeeObj {
NSLog(#"coffeeObj%#",coffeeObj);
int myInteger = [coffeeObj integerValue];
NSLog(#"myInteger%d",myInteger);
// print this myInteger0
NSLog(#"%#",coffeeArray);
//print object
if (sqlite3_open([self getDBPath], &database) == SQLITE_OK)
{
NSLog(#"myInteger%#",[self getDBPath]);
NSString *sql = [NSString stringWithFormat: #"delete from Coffee where CoffeeID =%d",myInteger];
const char *del_stmt = [sql UTF8String];
NSLog(#"%#",del_stmt); // getting print
// print this delete from Coffee where CoffeeID =0.
sqlite3_prepare_v2(database, del_stmt, -1, & deleteStmt, NULL);
NSLog(#"sqlite3_step(deleteStmt) == SQLITE_DONE%#",sqlite3_step(deleteStmt) == SQLITE_DONE);
// this print null
if (sqlite3_step(deleteStmt) == SQLITE_DONE)
{
//NSLog(#"hi") this is not getting print
} else {
//NSLog(#"hi") this is getting print
}
sqlite3_finalize(deleteStmt);
sqlite3_close(database);
[coffeeArray removeObjectAtIndex:myInteger];
NSLog(#"%#",coffeeArray);
// object is deleted
}
}
my table is like below
table name = Coffee
CoffeeID(INTEGER)=0
CoffeeName(VARCHAR)=Latte
Price(REAL)=2.99
where thing runs perfectly object get deleted from array and thats why its not appearing on table cell. but its not getting deleted from database table thats why it when i launch app again then it shows again please help what i am doing wrong.
Before start deleting the object just conform once the database is opened properly or not. Just try like this.
//Setting path
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent: #"database.db"]];
const char *dbpath=[databasePath UTF8String];
if (sqlite3_open(dbpath, &database) == SQLITE_OK)
{
NSString *sql = [NSString stringWithFormat: #"delete from Coffee where CoffeeID =%d",myInteger];
const char *del_stmt = [sql UTF8String];
sqlite3_prepare_v2(database, del_stmt, -1, & deleteStmt, NULL);
if (sqlite3_step(deleteStmt) == SQLITE_DONE)
{
} else {
}
sqlite3_finalize(deleteStmt);
sqlite3_close(database);
[coffeeArray removeObjectAtIndex:myInteger];
NSLog(#"%#",coffeeArray);
// object is deleted
}
if(sqlite3_open([[self filepath] UTF8String], &db) == SQLITE_OK)
{
Deletestatement = nil;
if(Deletestatement == nil)
{
const char *sql = "delete from Sqlitemanager2;";
if(sqlite3_prepare_v2(db, sql, -1, &Deletestatement, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating delete statement. '%s'", sqlite3_errmsg(db));
}
if (SQLITE_DONE != sqlite3_step(Deletestatement)) //prathibha for problem in if
NSAssert1(0, #"Error while deleting. '%s'", sqlite3_errmsg(db));
sqlite3_finalize(Deletestatement);
}
I hope this will help you.
the following code give me an library routine called out of sequence error, but I can't explain me where is the problem. Any ideas ?
- (BOOL)insertProduct:(Product *)product inOrder:(Order *)order withAmount:(int)amount
{
BOOL ok = NO;
sqlite3_stmt *statement;
const char *dbpath = [_databasePath UTF8String];
if (sqlite3_open(dbpath, &_database) == SQLITE_OK)
{
NSString * insertSQL;
int amount = [self getAmountForProduct:product inOrder:order];
NSLog(#"%i", amount);
if (amount != -1)
{
insertSQL = [NSString stringWithFormat: #"UPDATE ARTICOLIPERORDINE SET quantita = %i WHERE ordine = %i AND articolo = '%#'", amount, order.idOrdine, product.codice];
}
else
{
insertSQL = [NSString stringWithFormat: #"INSERT INTO ARTICOLIPERORDINE (ordine, articolo, quantita) VALUES(%i, '%#', %i)",order.idOrdine, product.codice, 1];
}
NSLog(#"%#", insertSQL);
const char *insert_stmt = [insertSQL UTF8String];
if (sqlite3_prepare_v2(_database, insert_stmt, -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_DONE)
{
ok = YES;
}
else
{
ok = NO;
NSLog(#"sqlite3 ERROR %s: %#",sqlite3_errmsg(_database), insertSQL);
}
sqlite3_finalize(statement);
sqlite3_close(_database);
}
else
{
NSLog(#"Error prepare = %s", sqlite3_errmsg(_database));
}
}
return ok;
}
The log print Error prepare = library routine called out of sequence
I have one approach.
Before this make sure that you have completed all your sql queries like connection open, close, finalize etc.
Before run your query actual into your code, execute that query into any database browser, You will see what is missing in your query.
As in my case I wrongly put the column name in query and run the code and I got the error multiple times. I review all the code carefully and execute the query into database browser and I found my mistake.
Hi i have made a function in my app delegate to remove the redundancy of my database , I am not sure do i have coded right as i have to perform nesting of SQL statements to find out the error in DB.
Can any body suggest me where i am wrong because the application is running well in simulator and crashing in Device.
I am even Not Sure where to Put finalize and sqlite3_close . Kindly help
-(void) removeRedundancy2
{
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dbPathString = [[docPaths objectAtIndex:0] stringByAppendingPathComponent:#"turfnutritiontool_ver_99.db"];
sqlite3_stmt *selectStmt;
sqlite3_stmt *selectStmt1;
BOOL isMyFileThere = [[NSFileManager defaultManager] fileExistsAtPath:dbPathString];
if (isMyFileThere)
{
if (sqlite3_open([dbPathString UTF8String], &database1)==SQLITE_OK)
{
// TO REMOVE FROM from tnt_scenario_product when NO ProductID Found
NSString *querySql2= [NSString stringWithFormat:#"SELECT productid from tnt_scenarioproduct"];
const char* query_sql2 = [querySql2 UTF8String];
if(sqlite3_prepare_v2(database1, query_sql2, -1, &selectStmt, NULL) == SQLITE_OK)
{
while (sqlite3_step(selectStmt) == SQLITE_ROW)
{
int productid = sqlite3_column_int(selectStmt, 0);
// NSLog(#"ProductId1 =%d",productid);
NSString *querySql21= [NSString stringWithFormat:#"SELECT productid from tnt_productcontent WHERE productid = %d",productid];
const char* query_sql21 = [querySql21 UTF8String];
if(sqlite3_prepare_v2(database1, query_sql21, -1, &selectStmt1, NULL) == SQLITE_OK)
{
if (sqlite3_step(selectStmt1) == SQLITE_ROW)
{
// DO NOTHING
}
else
{ // to delete scenario without product id
NSLog(#"Delete this Product from TPC 2 %d",productid);
NSString *querydelete2= [NSString stringWithFormat:#"DELETE from tnt_scenarioproduct WHERE productid = %d",productid];
const char* query_delete2 = [querydelete2 UTF8String];
char *error;
sqlite3_exec(database1, query_delete2, NULL, NULL, &error);
NSLog(#"error=%s ",error);
sqlite3_finalize(selectStmt1);
}
}
sqlite3_finalize(selectStmt1);
sqlite3_close(database1);
}
sqlite3_finalize(selectStmt);
}
sqlite3_close(database1);
}
sqlite3_close(database1);
}
}
After calling sqlite3_open, you must call sqlite3_close for that connection exactly once.
After calling sqlite3_prepare_v2, you must call sqlite3_finalize for that statement exactly once.
if (sqlite3_open([dbPathString UTF8String], &database1)==SQLITE_OK)
{
...
if(sqlite3_prepare_v2(database1, query_sql21, -1, &selectStmt1, NULL) == SQLITE_OK)
{
...
}
sqlite3_finalize(selectStmt);
....
}
sqlite3_close(database1);
Furthermore, you should not reuse the same variable (selectStmt) for two different queries to prevent confusion about its lifetime.