SlideShare una empresa de Scribd logo
1 de 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?

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (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
 

Destacado

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
 

Destacado (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 a 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 a 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
 

Más de 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
 

Más de 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
 

Último

DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dashnarutouzumaki53779
 
Ryan Mahoney - Will Artificial Intelligence Replace Real Estate Agents
Ryan Mahoney - Will Artificial Intelligence Replace Real Estate AgentsRyan Mahoney - Will Artificial Intelligence Replace Real Estate Agents
Ryan Mahoney - Will Artificial Intelligence Replace Real Estate AgentsRyan Mahoney
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 

Último (20)

DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Visualising and forecasting stocks using Dash
Visualising and forecasting stocks using DashVisualising and forecasting stocks using Dash
Visualising and forecasting stocks using Dash
 
Ryan Mahoney - Will Artificial Intelligence Replace Real Estate Agents
Ryan Mahoney - Will Artificial Intelligence Replace Real Estate AgentsRyan Mahoney - Will Artificial Intelligence Replace Real Estate Agents
Ryan Mahoney - Will Artificial Intelligence Replace Real Estate Agents
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 

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}

Notas del editor