SlideShare a Scribd company logo
1 of 143
SQLite Techniques
SQLite is....

Single-user

File-based

Simple

Cross Platform

A subset of full ANSI SQL
SQLite API


Pure C API

Lots of strange-looking, hard to
debug code

Best choice is to abstract it away
SQLite Tools



SQLite Manager Add-in for Firefox

sqlite3 command line utility
Writable Databases


Your app bundle is signed!

(That means the contents can't
change)
Your App Sandbox




Your App Bundle


       Resources
                   Documents
Your App Sandbox




Your App Bundle


       Resources
                   Documents
Creating the
  database
Getting Resource
      Paths
Getting Resource
                Paths

//fetches
path
for
foo.db
Getting Resource
                Paths

//fetches
path
for
foo.db
NSString
*resourcePath
=
[[NSBundle
mainBundle]
Getting Resource
                Paths

//fetches
path
for
foo.db
NSString
*resourcePath
=
[[NSBundle
mainBundle]





























pathForResource:@"foo"
Getting Resource
                Paths

//fetches
path
for
foo.db
NSString
*resourcePath
=
[[NSBundle
mainBundle]





























pathForResource:@"foo"





























ofType:@"db"];
Finding the Documents
      Directory
Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(

Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























NSDocumentDirectory,

Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























NSDocumentDirectory,




























NSUserDomainMask,

Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























NSDocumentDirectory,




























NSUserDomainMask,




























YES);
Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























NSDocumentDirectory,




























NSUserDomainMask,




























YES);

NSString
*documentsDirectory
=
[paths
objectAtIndex:0];
Copy a default
database on startup
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBundle]
   pathForResource:@"app" ofType:@"db"];

NSString *targetPath = ...
 NSFileManager *fm = [NSFileManager defaultManager];

if(![fm fileExistsAtPath:targetPath]) {
  [fm copyItemAtPath:sourcePath toPath:targetPath error:&error];
}
SQLite API Basics
Add the Framework
Add the Framework
Add the Framework
Add the Framework
SQLite API -
Opening a connection
SQLite API -
    Opening a connection
#import "sqlite3.h"
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result != SQLITE_OK) {
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result != SQLITE_OK) {
   [NSException raise:@"SQLITE ERROR"
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result != SQLITE_OK) {
   [NSException raise:@"SQLITE ERROR"
            format:@"Error %d", result];
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result != SQLITE_OK) {
   [NSException raise:@"SQLITE ERROR"
            format:@"Error %d", result];
}
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result != SQLITE_OK) {
   [NSException raise:@"SQLITE ERROR"
            format:@"Error %d", result];
}


//later
SQLite API -
    Opening a connection
#import "sqlite3.h"

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result != SQLITE_OK) {
   [NSException raise:@"SQLITE ERROR"
            format:@"Error %d", result];
}


//later
sqlite3_close(db);
SQLite API -
executing queries
SQLite API -
         executing queries
int sqlite3_exec(
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
     );
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
     );


//callback signature
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
     );


//callback signature
int RowCallback(void * context,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
     );


//callback signature
int RowCallback(void * context,
    int numColumns,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
     );


//callback signature
int RowCallback(void * context,
    int numColumns,
    char** colValues,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, int, char**, char**) callbackFunc,
     void *context,
     char **errorMessage
     );


//callback signature
int RowCallback(void * context,
    int numColumns,
    char** colValues,
    char ** colNames);
SQLite API -
 Prepared Statements


More Powerful

Unfortunately much more code!
SQLite API-Prepared Statements
SQLite API-Prepared Statements


sqlite3 *db;
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
   //handle error
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
   //handle error
}
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
   //handle error
}

//...
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
   //handle error
}

//...
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
   //handle error
}

//...
SQLite API-Prepared Statements


sqlite3 *db;
int result = sqlite3_open(DB_PATH, &db);
if(result != SQLITE_OK) {
   //handle error
}

sqlite3_stmt *stmt;
result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
if(result != SQLITE_OK) {
   //handle error
}

//...
SQLite API-Prepared Statements
SQLite API-Prepared Statements
//...
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

   [self processRow:row forStatement:stmt];
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

   [self processRow:row forStatement:stmt];

   [results addObject:row];
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

   [self processRow:row forStatement:stmt];

   [results addObject:row];
   result = sqlite3_step(stmt);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

    [self processRow:row forStatement:stmt];

    [results addObject:row];
    result = sqlite3_step(stmt);
}
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

    [self processRow:row forStatement:stmt];

    [results addObject:row];
    result = sqlite3_step(stmt);
}

sqlite_finalize(stmt);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

    [self processRow:row forStatement:stmt];

    [results addObject:row];
    result = sqlite3_step(stmt);
}

sqlite_finalize(stmt);
SQLite API-Prepared Statements
//...

//PARAMETERS HAVE A 1-BASED INDEX!
sqlite3_bind_int(stmt, 1 /* idx */, 5);
sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);

result = sqlite3_step(stmt);
if(result == SQLITE_DONE)
   return [NSArray array]; //nothing to do!

NSMutableArray *results = [NSMutableArray array];
while(result == SQLITE_ROW) {
  NSMutableDictionary *row = [NSMutableDictionary dictionary];

    [self processRow:row forStatement:stmt];

    [results addObject:row];
    result = sqlite3_step(stmt);
}

sqlite_finalize(stmt);

return results;
SQLite API-Prepared Statements
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
      value = [NSString stringWithFormat:@"%s", text];
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
      value = [NSString stringWithFormat:@"%s", text];
   } else {
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
      value = [NSString stringWithFormat:@"%s", text];
   } else {
      // more type handling
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
      value = [NSString stringWithFormat:@"%s", text];
   } else {
      // more type handling
   }
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
      value = [NSString stringWithFormat:@"%s", text];
   } else {
      // more type handling
   }
   [row setObject:value forKey:
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

   id value = [NSNull null];
   if(type == SQLITE_INTEGER) {
      value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
   } else if (type == SQLITE_TEXT) {
      const unsigned char * text = sqlite3_column_text(stmt, i);
      value = [NSString stringWithFormat:@"%s", text];
   } else {
      // more type handling
   }
   [row setObject:value forKey:
       [NSString stringWithUTF8String:colName]];
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

     id value = [NSNull null];
     if(type == SQLITE_INTEGER) {
        value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
     } else if (type == SQLITE_TEXT) {
        const unsigned char * text = sqlite3_column_text(stmt, i);
        value = [NSString stringWithFormat:@"%s", text];
     } else {
        // more type handling
     }
     [row setObject:value forKey:
         [NSString stringWithUTF8String:colName]];
 }
SQLite API-Prepared Statements


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int columnCount = sqlite3_column_count(stmt);
 for(int i=0; i<columnCount; i++) {
    //0-based index!
    const char * colName = sqlite3_column_name(stmt, i);
    int type = sqlite3_column_type(stmt, i);

        id value = [NSNull null];
        if(type == SQLITE_INTEGER) {
           value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
        } else if (type == SQLITE_TEXT) {
           const unsigned char * text = sqlite3_column_text(stmt, i);
           value = [NSString stringWithFormat:@"%s", text];
        } else {
           // more type handling
        }
        [row setObject:value forKey:
            [NSString stringWithUTF8String:colName]];
    }
}
FMDB


http://github.com/ccgus/fmdb
FMDB Usage
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
  while (i++ < 20) {
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
  while (i++ < 20) {
    [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
  while (i++ < 20) {
    [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,
       @"hi'", // look! I put in a ', and I'm not escaping it!
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
  while (i++ < 20) {
    [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,
       @"hi'", // look! I put in a ', and I'm not escaping it!
       [NSNumber numberWithInt:i]];
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
  while (i++ < 20) {
    [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,
       @"hi'", // look! I put in a ', and I'm not escaping it!
       [NSNumber numberWithInt:i]];
  }
FMDB Usage
  FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  if (![db open])
     NSLog(@"Could not open db.");

  [db executeUpdate:@"blah blah blah"];
    
  if ([db hadError])
   NSLog(@"Err %d: %@", [db lastErrorCode],
       [db lastErrorMessage]);

  [db executeUpdate:@"create table test (a text, b integer)"];

  [db beginTransaction];
  int i = 0;
  while (i++ < 20) {
    [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,
       @"hi'", // look! I put in a ', and I'm not escaping it!
       [NSNumber numberWithInt:i]];
  }
  [db commit];
What about updates?


Database is never copied over again

If we did, your customers would lose
data
Migrations

Concept from Ruby on Rails

Evolutionary database design

Each database has a "version"

App runs all migrations to the latest
version
Migrations

number        name
  1      initial_schema
  2        update_foo
  3      implement_blah
Migrations

number        name
  1      initial_schema
  2        update_foo
  3      implement_blah
Hand-rolled Database
      Migrator


 DEMO
FMDB Migration
       Manager


http://github.com/mocra/fmdb-
migration-manager
FMDB Migration
                  Manager

NSArray *migrations = [NSArray arrayWithObjects:
     [CreateStudents migration], // 1
     [CreateStaffMembers migration], // 2
     [AddStudentNumberToStudents migration], // 3
     nil
  ];
[FmdbMigrationManager executeForDatabasePath:@"/tmp/tmp.db"
withMigrations:migrations];
FMDB Migration
                      Manager
@interface CreateStudents : FmdbMigration
{
}
@end

@implementation CreateStudents
- (void)up {
  [self createTable:@"students" withColumns:[NSArray arrayWithObjects:
      [FmdbMigrationColumn columnWithColumnName:@"first_name" columnType:@"string"],
      [FmdbMigrationColumn columnWithColumnName:@"age" columnType:@"integer"
             defaultValue:21], nil];
}

- (void)down {
  [self dropTable:@"students"];
}

@end
ActiveRecord

Person *p = [[Person alloc] init];
p.name = @"Joe";
p.occupation = @"Dishwasher";

[p save];




Person *p = [Person personWithId:5];
==> Person {id:5, name:Joe, occupation:Dishwasher}
Aptiva's ActiveRecord


 http://github.com/aptiva/activerecord




                (YMMV)
Questions?

More Related Content

What's hot

Nouveau document texte
Nouveau document texteNouveau document texte
Nouveau document texteSai Ef
 
Yy
YyYy
Yyyygh
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveEleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]Eleanor McHugh
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?Alexandru Badiu
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionEleanor McHugh
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
 
Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)
Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)
Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)Kai Chan
 
Apache avro and overview hadoop tools
Apache avro and overview hadoop toolsApache avro and overview hadoop tools
Apache avro and overview hadoop toolsalireza alikhani
 
Ch3(working with file)
Ch3(working with file)Ch3(working with file)
Ch3(working with file)Chhom Karath
 
Filesystem Abstraction with Flysystem
Filesystem Abstraction with FlysystemFilesystem Abstraction with Flysystem
Filesystem Abstraction with FlysystemFrank de Jonge
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 

What's hot (20)

Nouveau document texte
Nouveau document texteNouveau document texte
Nouveau document texte
 
Yy
YyYy
Yy
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
 
C99.php
C99.phpC99.php
C99.php
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd edition
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
spug_2008-08
spug_2008-08spug_2008-08
spug_2008-08
 
Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)
Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)
Search Engine Building with Lucene and Solr (So Code Camp San Diego 2014)
 
Apache avro and overview hadoop tools
Apache avro and overview hadoop toolsApache avro and overview hadoop tools
Apache avro and overview hadoop tools
 
Ch3(working with file)
Ch3(working with file)Ch3(working with file)
Ch3(working with file)
 
Filesystem Abstraction with Flysystem
Filesystem Abstraction with FlysystemFilesystem Abstraction with Flysystem
Filesystem Abstraction with Flysystem
 
Linux intro 5 extra: awk
Linux intro 5 extra: awkLinux intro 5 extra: awk
Linux intro 5 extra: awk
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
The most exciting features of PHP 7.1
The most exciting features of PHP 7.1The most exciting features of PHP 7.1
The most exciting features of PHP 7.1
 
Scaling / optimizing search on netlog
Scaling / optimizing search on netlogScaling / optimizing search on netlog
Scaling / optimizing search on netlog
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
C99
C99C99
C99
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 

Viewers also liked

SQLite: Light, Open Source Relational Database Management System
SQLite: Light, Open Source Relational Database Management SystemSQLite: Light, Open Source Relational Database Management System
SQLite: Light, Open Source Relational Database Management SystemTanner Jessel
 
Sync It Up
Sync It UpSync It Up
Sync It Upsvoisen
 
SQLite3
SQLite3SQLite3
SQLite3cltru
 
EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...
EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...
EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...Dr.-Ing. Thomas Hartmann
 
Data sync on iOS with Couchbase Mobile
Data sync on iOS with Couchbase MobileData sync on iOS with Couchbase Mobile
Data sync on iOS with Couchbase MobileThiago Alencar
 
Integrating a Domain Ontology Development Environment and an Ontology Search ...
Integrating a Domain Ontology Development Environment and an Ontology Search ...Integrating a Domain Ontology Development Environment and an Ontology Search ...
Integrating a Domain Ontology Development Environment and an Ontology Search ...Takeshi Morita
 
Access ohne Access: Freie Datenbank-Frontends
Access ohne Access: Freie Datenbank-FrontendsAccess ohne Access: Freie Datenbank-Frontends
Access ohne Access: Freie Datenbank-FrontendsPeter Eisentraut
 
Advance sqlite3
Advance sqlite3Advance sqlite3
Advance sqlite3Raghu nath
 
(140625) #fitalk sq lite 소개와 구조 분석
(140625) #fitalk   sq lite 소개와 구조 분석(140625) #fitalk   sq lite 소개와 구조 분석
(140625) #fitalk sq lite 소개와 구조 분석INSIGHT FORENSIC
 
Python sqlite3 - flask
Python   sqlite3 - flaskPython   sqlite3 - flask
Python sqlite3 - flaskEueung Mulyana
 
C++ и базы данных
C++ и базы данныхC++ и базы данных
C++ и базы данныхmcroitor
 
Sqlite3 command reference
Sqlite3 command referenceSqlite3 command reference
Sqlite3 command referenceRaghu nath
 

Viewers also liked (20)

SQLite: Light, Open Source Relational Database Management System
SQLite: Light, Open Source Relational Database Management SystemSQLite: Light, Open Source Relational Database Management System
SQLite: Light, Open Source Relational Database Management System
 
SQLite - Overview
SQLite - OverviewSQLite - Overview
SQLite - Overview
 
Sync It Up
Sync It UpSync It Up
Sync It Up
 
C SQLite usage
C SQLite usageC SQLite usage
C SQLite usage
 
SQLite3
SQLite3SQLite3
SQLite3
 
Sqlite
SqliteSqlite
Sqlite
 
SQLite 3
SQLite 3SQLite 3
SQLite 3
 
Getting Started with SQLite
Getting Started with SQLiteGetting Started with SQLite
Getting Started with SQLite
 
EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...
EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...
EDDI 2011 - A Generic Multilevel Approach for Designing Domain Ontologies Bas...
 
Data sync on iOS with Couchbase Mobile
Data sync on iOS with Couchbase MobileData sync on iOS with Couchbase Mobile
Data sync on iOS with Couchbase Mobile
 
Integrating a Domain Ontology Development Environment and an Ontology Search ...
Integrating a Domain Ontology Development Environment and an Ontology Search ...Integrating a Domain Ontology Development Environment and an Ontology Search ...
Integrating a Domain Ontology Development Environment and an Ontology Search ...
 
Access ohne Access: Freie Datenbank-Frontends
Access ohne Access: Freie Datenbank-FrontendsAccess ohne Access: Freie Datenbank-Frontends
Access ohne Access: Freie Datenbank-Frontends
 
Advance sqlite3
Advance sqlite3Advance sqlite3
Advance sqlite3
 
(140625) #fitalk sq lite 소개와 구조 분석
(140625) #fitalk   sq lite 소개와 구조 분석(140625) #fitalk   sq lite 소개와 구조 분석
(140625) #fitalk sq lite 소개와 구조 분석
 
Python sqlite3 - flask
Python   sqlite3 - flaskPython   sqlite3 - flask
Python sqlite3 - flask
 
Sq lite presentation
Sq lite presentationSq lite presentation
Sq lite presentation
 
Aula 06 - TEP - Introdução SQLite
Aula 06 - TEP - Introdução SQLiteAula 06 - TEP - Introdução SQLite
Aula 06 - TEP - Introdução SQLite
 
C++ и базы данных
C++ и базы данныхC++ и базы данных
C++ и базы данных
 
Sqlite3 command reference
Sqlite3 command referenceSqlite3 command reference
Sqlite3 command reference
 
Python sqlite3
Python sqlite3Python sqlite3
Python sqlite3
 

Similar to SQLite Techniques

I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On RailsJohn Wilker
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
Ruby on Rails: Tasty Burgers
Ruby on Rails: Tasty BurgersRuby on Rails: Tasty Burgers
Ruby on Rails: Tasty BurgersAaron Patterson
 
Intoduction on Playframework
Intoduction on PlayframeworkIntoduction on Playframework
Intoduction on PlayframeworkKnoldus Inc.
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Elena Kolevska
 
Laravel dokumentacja Restful API - swagger
Laravel dokumentacja Restful API - swaggerLaravel dokumentacja Restful API - swagger
Laravel dokumentacja Restful API - swaggerLaravel Poland MeetUp
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
JavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsJavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsKonrad Malawski
 
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...Databricks
 
30 5 Database Jdbc
30 5 Database Jdbc30 5 Database Jdbc
30 5 Database Jdbcphanleson
 
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docx
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docxWeb CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docx
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docxcelenarouzie
 
Introduction to the New Asynchronous API in the .NET Driver
Introduction to the New Asynchronous API in the .NET DriverIntroduction to the New Asynchronous API in the .NET Driver
Introduction to the New Asynchronous API in the .NET DriverMongoDB
 
Web2py Code Lab
Web2py Code LabWeb2py Code Lab
Web2py Code LabColin Su
 
Intorduction of Playframework
Intorduction of PlayframeworkIntorduction of Playframework
Intorduction of Playframeworkmaltiyadav
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 

Similar to SQLite Techniques (20)

I Phone On Rails
I Phone On RailsI Phone On Rails
I Phone On Rails
 
3 database-jdbc(1)
3 database-jdbc(1)3 database-jdbc(1)
3 database-jdbc(1)
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Ruby on Rails: Tasty Burgers
Ruby on Rails: Tasty BurgersRuby on Rails: Tasty Burgers
Ruby on Rails: Tasty Burgers
 
Intoduction on Playframework
Intoduction on PlayframeworkIntoduction on Playframework
Intoduction on Playframework
 
Spring boot
Spring boot Spring boot
Spring boot
 
Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5Bootstrat REST APIs with Laravel 5
Bootstrat REST APIs with Laravel 5
 
Laravel dokumentacja Restful API - swagger
Laravel dokumentacja Restful API - swaggerLaravel dokumentacja Restful API - swagger
Laravel dokumentacja Restful API - swagger
 
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
HelsinkiJS meet-up. Dmitry Soshnikov - ECMAScript 6
 
Java 8: the good parts!
Java 8: the good parts!Java 8: the good parts!
Java 8: the good parts!
 
JavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good PartsJavaOne 2013: Java 8 - The Good Parts
JavaOne 2013: Java 8 - The Good Parts
 
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
From HelloWorld to Configurable and Reusable Apache Spark Applications in Sca...
 
занятие8
занятие8занятие8
занятие8
 
30 5 Database Jdbc
30 5 Database Jdbc30 5 Database Jdbc
30 5 Database Jdbc
 
Twitter codeigniter library
Twitter codeigniter libraryTwitter codeigniter library
Twitter codeigniter library
 
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docx
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docxWeb CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docx
Web CrawlersrcedusmulylecrawlerController.javaWeb Crawler.docx
 
Introduction to the New Asynchronous API in the .NET Driver
Introduction to the New Asynchronous API in the .NET DriverIntroduction to the New Asynchronous API in the .NET Driver
Introduction to the New Asynchronous API in the .NET Driver
 
Web2py Code Lab
Web2py Code LabWeb2py Code Lab
Web2py Code Lab
 
Intorduction of Playframework
Intorduction of PlayframeworkIntorduction of Playframework
Intorduction of Playframework
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 

More from joaopmaia

AFNetworking
AFNetworking AFNetworking
AFNetworking joaopmaia
 
Core Data presentation
Core Data presentationCore Data presentation
Core Data presentationjoaopmaia
 
Meetup uikit programming
Meetup uikit programmingMeetup uikit programming
Meetup uikit programmingjoaopmaia
 
Web App Testing With Selenium
Web App Testing With SeleniumWeb App Testing With Selenium
Web App Testing With Seleniumjoaopmaia
 
Eventum Presentation
Eventum PresentationEventum Presentation
Eventum Presentationjoaopmaia
 
Form Validation NG
Form Validation NGForm Validation NG
Form Validation NGjoaopmaia
 

More from joaopmaia (6)

AFNetworking
AFNetworking AFNetworking
AFNetworking
 
Core Data presentation
Core Data presentationCore Data presentation
Core Data presentation
 
Meetup uikit programming
Meetup uikit programmingMeetup uikit programming
Meetup uikit programming
 
Web App Testing With Selenium
Web App Testing With SeleniumWeb App Testing With Selenium
Web App Testing With Selenium
 
Eventum Presentation
Eventum PresentationEventum Presentation
Eventum Presentation
 
Form Validation NG
Form Validation NGForm Validation NG
Form Validation NG
 

Recently uploaded

"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbuapidays
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024The Digital Insurer
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyKhushali Kathiriya
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsNanddeep Nachan
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusZilliz
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 

Recently uploaded (20)

"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu SubbuApidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
Apidays Singapore 2024 - Modernizing Securities Finance by Madhu Subbu
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
A Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source MilvusA Beginners Guide to Building a RAG App Using Open Source Milvus
A Beginners Guide to Building a RAG App Using Open Source Milvus
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 

SQLite Techniques

  • 3. SQLite API Pure C API Lots of strange-looking, hard to debug code Best choice is to abstract it away
  • 4. SQLite Tools SQLite Manager Add-in for Firefox sqlite3 command line utility
  • 5. Writable Databases Your app bundle is signed! (That means the contents can't change)
  • 6. Your App Sandbox Your App Bundle Resources Documents
  • 7. Your App Sandbox Your App Bundle Resources Documents
  • 8. Creating the database
  • 10. Getting Resource Paths //fetches
path
for
foo.db
  • 11. Getting Resource Paths //fetches
path
for
foo.db NSString
*resourcePath
=
[[NSBundle
mainBundle]
  • 12. Getting Resource Paths //fetches
path
for
foo.db NSString
*resourcePath
=
[[NSBundle
mainBundle] 




























pathForResource:@"foo"
  • 13. Getting Resource Paths //fetches
path
for
foo.db NSString
*resourcePath
=
[[NSBundle
mainBundle] 




























pathForResource:@"foo" 




























ofType:@"db"];
  • 15. Finding the Documents Directory NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(

  • 16. Finding the Documents Directory NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(
 


























NSDocumentDirectory,

  • 17. Finding the Documents Directory NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(
 


























NSDocumentDirectory,
 


























NSUserDomainMask,

  • 18. Finding the Documents Directory NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(
 


























NSDocumentDirectory,
 


























NSUserDomainMask,
 


























YES);
  • 19. Finding the Documents Directory NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(
 


























NSDocumentDirectory,
 


























NSUserDomainMask,
 


























YES); NSString
*documentsDirectory
=
[paths
objectAtIndex:0];
  • 21. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 22. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 23. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 24. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 25. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 26. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 27. Copy a default database on startup //in applicationDidFinishLaunching NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@"app" ofType:@"db"]; NSString *targetPath = ... NSFileManager *fm = [NSFileManager defaultManager]; if(![fm fileExistsAtPath:targetPath]) { [fm copyItemAtPath:sourcePath toPath:targetPath error:&error]; }
  • 33. SQLite API - Opening a connection
  • 34. SQLite API - Opening a connection #import "sqlite3.h"
  • 35. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db;
  • 36. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db);
  • 37. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) {
  • 38. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) { [NSException raise:@"SQLITE ERROR"
  • 39. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) { [NSException raise:@"SQLITE ERROR" format:@"Error %d", result];
  • 40. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) { [NSException raise:@"SQLITE ERROR" format:@"Error %d", result]; }
  • 41. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) { [NSException raise:@"SQLITE ERROR" format:@"Error %d", result]; } //later
  • 42. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) { [NSException raise:@"SQLITE ERROR" format:@"Error %d", result]; } //later sqlite3_close(db);
  • 44. SQLite API - executing queries int sqlite3_exec(
  • 45. SQLite API - executing queries int sqlite3_exec( sqlite3 *db,
  • 46. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql,
  • 47. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc,
  • 48. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context,
  • 49. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage
  • 50. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage );
  • 51. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage ); //callback signature
  • 52. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage ); //callback signature int RowCallback(void * context,
  • 53. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage ); //callback signature int RowCallback(void * context, int numColumns,
  • 54. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage ); //callback signature int RowCallback(void * context, int numColumns, char** colValues,
  • 55. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage ); //callback signature int RowCallback(void * context, int numColumns, char** colValues, char ** colNames);
  • 56. SQLite API - Prepared Statements More Powerful Unfortunately much more code!
  • 59. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db);
  • 60. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) {
  • 61. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error
  • 62. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error }
  • 63. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error }
  • 64. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt;
  • 65. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL);
  • 66. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) {
  • 67. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) { //handle error
  • 68. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) { //handle error }
  • 69. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) { //handle error } //...
  • 70. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) { //handle error } //...
  • 71. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) { //handle error } //...
  • 72. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; result = sqlite3_prepare_v2(db, sql_cstring, -1, &stmt, NULL); if(result != SQLITE_OK) { //handle error } //...
  • 76. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5);
  • 77. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);
  • 78. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT);
  • 79. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt);
  • 80. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE)
  • 81. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do!
  • 82. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do!
  • 83. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array];
  • 84. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) {
  • 85. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary];
  • 86. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary];
  • 87. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt];
  • 88. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt]; [results addObject:row];
  • 89. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt]; [results addObject:row]; result = sqlite3_step(stmt);
  • 90. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt]; [results addObject:row]; result = sqlite3_step(stmt); }
  • 91. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt]; [results addObject:row]; result = sqlite3_step(stmt); } sqlite_finalize(stmt);
  • 92. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt]; [results addObject:row]; result = sqlite3_step(stmt); } sqlite_finalize(stmt);
  • 93. SQLite API-Prepared Statements //... //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); result = sqlite3_step(stmt); if(result == SQLITE_DONE) return [NSArray array]; //nothing to do! NSMutableArray *results = [NSMutableArray array]; while(result == SQLITE_ROW) { NSMutableDictionary *row = [NSMutableDictionary dictionary]; [self processRow:row forStatement:stmt]; [results addObject:row]; result = sqlite3_step(stmt); } sqlite_finalize(stmt); return results;
  • 96. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt);
  • 97. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) {
  • 98. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index!
  • 99. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i);
  • 100. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i);
  • 101. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null];
  • 102. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) {
  • 103. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)];
  • 104. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) {
  • 105. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i);
  • 106. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text];
  • 107. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else {
  • 108. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else { // more type handling
  • 109. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else { // more type handling }
  • 110. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else { // more type handling } [row setObject:value forKey:
  • 111. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else { // more type handling } [row setObject:value forKey: [NSString stringWithUTF8String:colName]];
  • 112. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else { // more type handling } [row setObject:value forKey: [NSString stringWithUTF8String:colName]]; }
  • 113. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); for(int i=0; i<columnCount; i++) { //0-based index! const char * colName = sqlite3_column_name(stmt, i); int type = sqlite3_column_type(stmt, i); id value = [NSNull null]; if(type == SQLITE_INTEGER) { value = [NSNumber numberWithInt:sqlite3_column_int(stmt, i)]; } else if (type == SQLITE_TEXT) { const unsigned char * text = sqlite3_column_text(stmt, i); value = [NSString stringWithFormat:@"%s", text]; } else { // more type handling } [row setObject:value forKey: [NSString stringWithUTF8String:colName]]; } }
  • 116. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
  • 117. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])
  • 118. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");
  • 119. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];
  • 120. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];     
  • 121. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])
  • 122. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode],
  • 123. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
  • 124. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];
  • 125. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];
  • 126. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;
  • 127. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;   while (i++ < 20) {
  • 128. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;   while (i++ < 20) {   [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,
  • 129. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;   while (i++ < 20) {   [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,        @"hi'", // look! I put in a ', and I'm not escaping it!
  • 130. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;   while (i++ < 20) {   [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,        @"hi'", // look! I put in a ', and I'm not escaping it!        [NSNumber numberWithInt:i]];
  • 131. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;   while (i++ < 20) {   [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,        @"hi'", // look! I put in a ', and I'm not escaping it!        [NSNumber numberWithInt:i]];   }
  • 132. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];        if ([db hadError])    NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);   [db executeUpdate:@"create table test (a text, b integer)"];   [db beginTransaction];   int i = 0;   while (i++ < 20) {   [db executeUpdate:@"insert into test (a, b) values (?, ?)" ,        @"hi'", // look! I put in a ', and I'm not escaping it!        [NSNumber numberWithInt:i]];   }   [db commit];
  • 133. What about updates? Database is never copied over again If we did, your customers would lose data
  • 134. Migrations Concept from Ruby on Rails Evolutionary database design Each database has a "version" App runs all migrations to the latest version
  • 135. Migrations number name 1 initial_schema 2 update_foo 3 implement_blah
  • 136. Migrations number name 1 initial_schema 2 update_foo 3 implement_blah
  • 137. Hand-rolled Database Migrator DEMO
  • 138. FMDB Migration Manager http://github.com/mocra/fmdb- migration-manager
  • 139. FMDB Migration Manager NSArray *migrations = [NSArray arrayWithObjects: [CreateStudents migration], // 1 [CreateStaffMembers migration], // 2 [AddStudentNumberToStudents migration], // 3 nil ]; [FmdbMigrationManager executeForDatabasePath:@"/tmp/tmp.db" withMigrations:migrations];
  • 140. FMDB Migration Manager @interface CreateStudents : FmdbMigration { } @end @implementation CreateStudents - (void)up { [self createTable:@"students" withColumns:[NSArray arrayWithObjects: [FmdbMigrationColumn columnWithColumnName:@"first_name" columnType:@"string"], [FmdbMigrationColumn columnWithColumnName:@"age" columnType:@"integer" defaultValue:21], nil]; } - (void)down { [self dropTable:@"students"]; } @end
  • 141. ActiveRecord Person *p = [[Person alloc] init]; p.name = @"Joe"; p.occupation = @"Dishwasher"; [p save]; Person *p = [Person personWithId:5]; ==> Person {id:5, name:Joe, occupation:Dishwasher}

Editor's Notes