SlideShare una empresa de Scribd logo
1 de 143
Descargar para leer sin conexión
SQLite Techniques

                              Ben Scheirman
                               @subdigital

                 Code / Slides:
       github.com/subdigital/iphonedevcon-
                    sandiego

Tuesday, September 28, 2010
SQLite is....

                 Single-user

                 File-based

                 Simple

                 Cross Platform

                 A subset of full ANSI SQL



Tuesday, September 28, 2010
SQLite API


                 Pure C API

                 Lots of strange-looking, hard to
                 debug code

                 Best choice is to abstract it away




Tuesday, September 28, 2010
SQLite Tools



                 SQLite Manager Add-in for Firefox

                 sqlite3 command line utility




Tuesday, September 28, 2010
Writable Databases


                 Your app bundle is signed!

                 (That means the contents can't
                 change)




Tuesday, September 28, 2010
Your App Sandbox




                              Your App Bundle


                                     Resources
                                                 Documents




Tuesday, September 28, 2010
Your App Sandbox




                              Your App Bundle


                                     Resources
                                                 Documents




Tuesday, September 28, 2010
Creating the
                            database


Tuesday, September 28, 2010
Getting Resource
                           Paths




Tuesday, September 28, 2010
Getting Resource
                           Paths

  //fetches	
  path	
  for	
  foo.db




Tuesday, September 28, 2010
Getting Resource
                           Paths

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




Tuesday, September 28, 2010
Getting Resource
                                   Paths

  //fetches	
  path	
  for	
  foo.db
  NSString	
  *resourcePath	
  =	
  [[NSBundle	
  mainBundle]
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pathForResource:@"foo"




Tuesday, September 28, 2010
Getting Resource
                                   Paths

  //fetches	
  path	
  for	
  foo.db
  NSString	
  *resourcePath	
  =	
  [[NSBundle	
  mainBundle]
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  pathForResource:@"foo"
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ofType:@"db"];




Tuesday, September 28, 2010
Finding the Documents
              Directory




Tuesday, September 28, 2010
Finding the Documents
              Directory

            NSArray	
  *paths	
  =	
  NSSearchPathForDirectoriesInDomains(	
  




Tuesday, September 28, 2010
Finding the Documents
              Directory

            NSArray	
  *paths	
  =	
  NSSearchPathForDirectoriesInDomains(	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSDocumentDirectory,	
  




Tuesday, September 28, 2010
Finding the Documents
              Directory

            NSArray	
  *paths	
  =	
  NSSearchPathForDirectoriesInDomains(	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSDocumentDirectory,	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSUserDomainMask,	
  




Tuesday, September 28, 2010
Finding the Documents
              Directory

            NSArray	
  *paths	
  =	
  NSSearchPathForDirectoriesInDomains(	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSDocumentDirectory,	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSUserDomainMask,	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  YES);




Tuesday, September 28, 2010
Finding the Documents
              Directory

            NSArray	
  *paths	
  =	
  NSSearchPathForDirectoriesInDomains(	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSDocumentDirectory,	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  NSUserDomainMask,	
  
            	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  YES);

            NSString	
  *documentsDirectory	
  =	
  [paths	
  objectAtIndex:0];




Tuesday, September 28, 2010
Copy a default
              database on startup




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
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];
         }




Tuesday, September 28, 2010
SQLite API Basics




Tuesday, September 28, 2010
Add the Framework




Tuesday, September 28, 2010
Add the Framework




Tuesday, September 28, 2010
Add the Framework




Tuesday, September 28, 2010
Add the Framework




Tuesday, September 28, 2010
SQLite API -
           Opening a connection




Tuesday, September 28, 2010
SQLite API -
           Opening a connection
     #import "sqlite3.h"




Tuesday, September 28, 2010
SQLite API -
           Opening a connection
     #import "sqlite3.h"

     sqlite3 *db;




Tuesday, September 28, 2010
SQLite API -
           Opening a connection
     #import "sqlite3.h"

     sqlite3 *db;

     int result = sqlite3_open(PATH, &db);




Tuesday, September 28, 2010
SQLite API -
           Opening a connection
     #import "sqlite3.h"

     sqlite3 *db;

     int result = sqlite3_open(PATH, &db);
     if (result != SQLITE_OK) {




Tuesday, September 28, 2010
SQLite API -
           Opening a connection
     #import "sqlite3.h"

     sqlite3 *db;

     int result = sqlite3_open(PATH, &db);
     if (result != SQLITE_OK) {
        [NSException raise:@"SQLITE ERROR"




Tuesday, September 28, 2010
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];




Tuesday, September 28, 2010
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];
     }




Tuesday, September 28, 2010
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




Tuesday, September 28, 2010
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);




Tuesday, September 28, 2010
SQLite API -
                   executing queries




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,
        char *sql,




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,
        char *sql,
        int (*callback)(void *, int, char**, char**) callbackFunc,




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,
        char *sql,
        int (*callback)(void *, int, char**, char**) callbackFunc,
        void *context,




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,
        char *sql,
        int (*callback)(void *, int, char**, char**) callbackFunc,
        void *context,
        char **errorMessage




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,
        char *sql,
        int (*callback)(void *, int, char**, char**) callbackFunc,
        void *context,
        char **errorMessage
        );




Tuesday, September 28, 2010
SQLite API -
                   executing queries
     int sqlite3_exec(
        sqlite3 *db,
        char *sql,
        int (*callback)(void *, int, char**, char**) callbackFunc,
        void *context,
        char **errorMessage
        );


     //callback signature




Tuesday, September 28, 2010
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,




Tuesday, September 28, 2010
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,




Tuesday, September 28, 2010
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,




Tuesday, September 28, 2010
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);




Tuesday, September 28, 2010
SQLite API -
              Prepared Statements


           More Powerful

           Unfortunately much more code!




Tuesday, September 28, 2010
SQLite API-Prepared Statements




Tuesday, September 28, 2010
SQLite API-Prepared Statements


        sqlite3 *db;




Tuesday, September 28, 2010
SQLite API-Prepared Statements


        sqlite3 *db;
        int result = sqlite3_open(DB_PATH, &db);




Tuesday, September 28, 2010
SQLite API-Prepared Statements


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




Tuesday, September 28, 2010
SQLite API-Prepared Statements


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




Tuesday, September 28, 2010
SQLite API-Prepared Statements


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




Tuesday, September 28, 2010
SQLite API-Prepared Statements


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




Tuesday, September 28, 2010
SQLite API-Prepared Statements


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

        sqlite3_stmt *stmt;




Tuesday, September 28, 2010
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);




Tuesday, September 28, 2010
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) {




Tuesday, September 28, 2010
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




Tuesday, September 28, 2010
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
        }




Tuesday, September 28, 2010
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
        }

        //...




Tuesday, September 28, 2010
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
        }

        //...




Tuesday, September 28, 2010
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
        }

        //...




Tuesday, September 28, 2010
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
        }

        //...




Tuesday, September 28, 2010
SQLite API-Prepared Statements




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //PARAMETERS HAVE A 1-BASED INDEX!




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //PARAMETERS HAVE A 1-BASED INDEX!
      sqlite3_bind_int(stmt, 1 /* idx */, 5);




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

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




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

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




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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);




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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)




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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!




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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!




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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];




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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) {




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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];




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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];




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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];




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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];




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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);




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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);
      }




Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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);



Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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);



Tuesday, September 28, 2010
SQLite API-Prepared Statements
      //INSERT INTO CARS(year, make) VALUES(?, ?)

      //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;
Tuesday, September 28, 2010
SQLite API-Prepared Statements




Tuesday, September 28, 2010
SQLite API-Prepared Statements

-(void)processRow:(NSMutableDictionary *)row forStatement:
(sqlite3_stmt*)stmt {




Tuesday, September 28, 2010
SQLite API-Prepared Statements

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




Tuesday, September 28, 2010
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++) {




Tuesday, September 28, 2010
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!




Tuesday, September 28, 2010
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);




Tuesday, September 28, 2010
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);




Tuesday, September 28, 2010
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];




Tuesday, September 28, 2010
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) {




Tuesday, September 28, 2010
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)];




Tuesday, September 28, 2010
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) {




Tuesday, September 28, 2010
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);




Tuesday, September 28, 2010
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];




Tuesday, September 28, 2010
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 {




Tuesday, September 28, 2010
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




Tuesday, September 28, 2010
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
          }




Tuesday, September 28, 2010
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:



Tuesday, September 28, 2010
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]];


Tuesday, September 28, 2010
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]];
   }

Tuesday, September 28, 2010
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]];
    }
}
Tuesday, September 28, 2010
FMDB


                 http://github.com/ccgus/fmdb




Tuesday, September 28, 2010
FMDB Usage




Tuesday, September 28, 2010
FMDB Usage
           FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];




Tuesday, September 28, 2010
FMDB Usage
           FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
           if (![db open])




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




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

           [db executeUpdate:@"blah blah blah"];




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

           [db executeUpdate:@"blah blah blah"];
             




Tuesday, September 28, 2010
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])




Tuesday, September 28, 2010
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],




Tuesday, September 28, 2010
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]);




Tuesday, September 28, 2010
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)"];




Tuesday, September 28, 2010
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];




Tuesday, September 28, 2010
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;




Tuesday, September 28, 2010
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) {




Tuesday, September 28, 2010
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 (?, ?)" ,




Tuesday, September 28, 2010
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!




Tuesday, September 28, 2010
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]];


Tuesday, September 28, 2010
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]];
           }

Tuesday, September 28, 2010
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];
Tuesday, September 28, 2010
What about updates?


                 Database is never copied over again

                 If we did, your customers would lose
                 data




Tuesday, September 28, 2010
Migrations

                 Concept from Ruby on Rails

                 Evolutionary database design

                 Each database has a "version"

                 App runs all migrations to the latest
                 version




Tuesday, September 28, 2010
Migrations

                              number        name
                                1      initial_schema
                                2        update_foo
                                3      implement_blah




Tuesday, September 28, 2010
Migrations

                              number        name
                                1      initial_schema
                                2        update_foo
                                3      implement_blah




Tuesday, September 28, 2010
Hand-rolled Database
                 Migrator


                 DEMO




Tuesday, September 28, 2010
FMDB Migration
                                  Manager


                 http://github.com/mocra/fmdb-
                 migration-manager




Tuesday, September 28, 2010
FMDB Migration
                                  Manager

 NSArray *migrations = [NSArray arrayWithObjects:
      [CreateStudents migration], // 1
      [CreateStaffMembers migration], // 2
      [AddStudentNumberToStudents migration], // 3
      nil
   ];
 [FmdbMigrationManager executeForDatabasePath:@"/tmp/tmp.db"
 withMigrations:migrations];




Tuesday, September 28, 2010
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




Tuesday, September 28, 2010
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}




Tuesday, September 28, 2010
Aptiva's ActiveRecord


                  http://github.com/aptiva/activerecord




                                 (YMMV)




Tuesday, September 28, 2010
Questions?




Tuesday, September 28, 2010

Más contenido relacionado

La actualidad más candente

Yy
YyYy
Yy
yygh
 
Nouveau document texte
Nouveau document texteNouveau document texte
Nouveau document texte
Sai Ef
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
Fabien Potencier
 
Letting In the Light: Using Solr as an External Search Component
Letting In the Light: Using Solr as an External Search ComponentLetting In the Light: Using Solr as an External Search Component
Letting In the Light: Using Solr as an External Search Component
Jay Luker
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
Hugo Hamon
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
Fabien Potencier
 

La actualidad más candente (20)

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]
 
Yy
YyYy
Yy
 
Nouveau document texte
Nouveau document texteNouveau document texte
Nouveau document texte
 
Looping the Loop with SPL Iterators
Looping the Loop with SPL IteratorsLooping the Loop with SPL Iterators
Looping the Loop with SPL Iterators
 
C99.php
C99.phpC99.php
C99.php
 
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
 
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?
 
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
 
Filesystem Abstraction with Flysystem
Filesystem Abstraction with FlysystemFilesystem Abstraction with Flysystem
Filesystem Abstraction with Flysystem
 
Ch3(working with file)
Ch3(working with file)Ch3(working with file)
Ch3(working with file)
 
C99
C99C99
C99
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Scaling / optimizing search on netlog
Scaling / optimizing search on netlogScaling / optimizing search on netlog
Scaling / optimizing search on netlog
 
Letting In the Light: Using Solr as an External Search Component
Letting In the Light: Using Solr as an External Search ComponentLetting In the Light: Using Solr as an External Search Component
Letting In the Light: Using Solr as an External Search Component
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
JavaScript Classes and Inheritance
JavaScript Classes and InheritanceJavaScript Classes and Inheritance
JavaScript Classes and Inheritance
 
Psycopg2 - Connect to PostgreSQL using Python Script
Psycopg2 - Connect to PostgreSQL using Python ScriptPsycopg2 - Connect to PostgreSQL using Python Script
Psycopg2 - Connect to PostgreSQL using Python Script
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Cod
CodCod
Cod
 

Similar a SQLite Techniques

iPhone for .NET Developers
iPhone for .NET DevelopersiPhone for .NET Developers
iPhone for .NET Developers
Ben Scheirman
 
MDSD for iPhone and Android
MDSD for iPhone and AndroidMDSD for iPhone and Android
MDSD for iPhone and Android
Heiko Behrens
 
Large problems, Mostly Solved
Large problems, Mostly SolvedLarge problems, Mostly Solved
Large problems, Mostly Solved
ericholscher
 
Fabric-让部署变得简单
Fabric-让部署变得简单Fabric-让部署变得简单
Fabric-让部署变得简单
Eric Lo
 

Similar a SQLite Techniques (20)

iPhone for .NET Developers
iPhone for .NET DevelopersiPhone for .NET Developers
iPhone for .NET Developers
 
MDSD for iPhone and Android
MDSD for iPhone and AndroidMDSD for iPhone and Android
MDSD for iPhone and Android
 
09 Data
09 Data09 Data
09 Data
 
Mongo db
Mongo dbMongo db
Mongo db
 
занятие8
занятие8занятие8
занятие8
 
Lecture 2#- (Intro to Obj-C, Interface Builder and Xcode)
Lecture 2#- (Intro to Obj-C, Interface Builder and Xcode)Lecture 2#- (Intro to Obj-C, Interface Builder and Xcode)
Lecture 2#- (Intro to Obj-C, Interface Builder and Xcode)
 
Techfest 2013 No RESTKit for the Weary
Techfest 2013 No RESTKit for the WearyTechfest 2013 No RESTKit for the Weary
Techfest 2013 No RESTKit for the Weary
 
EC3 Workshop - Evernote API with Mobile SDKs
EC3 Workshop - Evernote API with Mobile SDKs EC3 Workshop - Evernote API with Mobile SDKs
EC3 Workshop - Evernote API with Mobile SDKs
 
Metaprogramming
MetaprogrammingMetaprogramming
Metaprogramming
 
Data Loading for Ext GWT
Data Loading for Ext GWTData Loading for Ext GWT
Data Loading for Ext GWT
 
XQuery Design Patterns
XQuery Design PatternsXQuery Design Patterns
XQuery Design Patterns
 
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHPIPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
IPC2010SE Doctrine2 Enterprise Persistence Layer for PHP
 
Continuous Integration Testing for Plone Using Hudson
Continuous Integration Testing for Plone Using HudsonContinuous Integration Testing for Plone Using Hudson
Continuous Integration Testing for Plone Using Hudson
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
Large problems, Mostly Solved
Large problems, Mostly SolvedLarge problems, Mostly Solved
Large problems, Mostly Solved
 
Fabric-让部署变得简单
Fabric-让部署变得简单Fabric-让部署变得简单
Fabric-让部署变得简单
 
Acceptance & Integration Testing With Behat (PBC11)
Acceptance & Integration Testing With Behat (PBC11)Acceptance & Integration Testing With Behat (PBC11)
Acceptance & Integration Testing With Behat (PBC11)
 
Desenvolvendo Aplicativos Sociais com Rails 3
Desenvolvendo Aplicativos Sociais com Rails 3Desenvolvendo Aplicativos Sociais com Rails 3
Desenvolvendo Aplicativos Sociais com Rails 3
 
Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
Mastering the AWS SDK for PHP (TLS306) | AWS re:Invent 2013
 
Developing in HTML5: Widgetbox & Sencha Touch
Developing in HTML5: Widgetbox & Sencha TouchDeveloping in HTML5: Widgetbox & Sencha Touch
Developing in HTML5: Widgetbox & Sencha Touch
 

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

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Último (20)

ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot ModelNavi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Navi Mumbai Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
Apidays Singapore 2024 - Scalable LLM APIs for AI and Generative AI Applicati...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 

SQLite Techniques

  • 1. SQLite Techniques Ben Scheirman @subdigital Code / Slides: github.com/subdigital/iphonedevcon- sandiego Tuesday, September 28, 2010
  • 2. SQLite is.... Single-user File-based Simple Cross Platform A subset of full ANSI SQL Tuesday, September 28, 2010
  • 3. SQLite API Pure C API Lots of strange-looking, hard to debug code Best choice is to abstract it away Tuesday, September 28, 2010
  • 4. SQLite Tools SQLite Manager Add-in for Firefox sqlite3 command line utility Tuesday, September 28, 2010
  • 5. Writable Databases Your app bundle is signed! (That means the contents can't change) Tuesday, September 28, 2010
  • 6. Your App Sandbox Your App Bundle Resources Documents Tuesday, September 28, 2010
  • 7. Your App Sandbox Your App Bundle Resources Documents Tuesday, September 28, 2010
  • 8. Creating the database Tuesday, September 28, 2010
  • 9. Getting Resource Paths Tuesday, September 28, 2010
  • 10. Getting Resource Paths //fetches  path  for  foo.db Tuesday, September 28, 2010
  • 11. Getting Resource Paths //fetches  path  for  foo.db NSString  *resourcePath  =  [[NSBundle  mainBundle] Tuesday, September 28, 2010
  • 12. Getting Resource Paths //fetches  path  for  foo.db NSString  *resourcePath  =  [[NSBundle  mainBundle]                                                          pathForResource:@"foo" Tuesday, September 28, 2010
  • 13. Getting Resource Paths //fetches  path  for  foo.db NSString  *resourcePath  =  [[NSBundle  mainBundle]                                                          pathForResource:@"foo"                                                          ofType:@"db"]; Tuesday, September 28, 2010
  • 14. Finding the Documents Directory Tuesday, September 28, 2010
  • 15. Finding the Documents Directory NSArray  *paths  =  NSSearchPathForDirectoriesInDomains(   Tuesday, September 28, 2010
  • 16. Finding the Documents Directory NSArray  *paths  =  NSSearchPathForDirectoriesInDomains(                                                        NSDocumentDirectory,   Tuesday, September 28, 2010
  • 17. Finding the Documents Directory NSArray  *paths  =  NSSearchPathForDirectoriesInDomains(                                                        NSDocumentDirectory,                                                        NSUserDomainMask,   Tuesday, September 28, 2010
  • 18. Finding the Documents Directory NSArray  *paths  =  NSSearchPathForDirectoriesInDomains(                                                        NSDocumentDirectory,                                                        NSUserDomainMask,                                                        YES); Tuesday, September 28, 2010
  • 19. Finding the Documents Directory NSArray  *paths  =  NSSearchPathForDirectoriesInDomains(                                                        NSDocumentDirectory,                                                        NSUserDomainMask,                                                        YES); NSString  *documentsDirectory  =  [paths  objectAtIndex:0]; Tuesday, September 28, 2010
  • 20. Copy a default database on startup Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 28. SQLite API Basics Tuesday, September 28, 2010
  • 29. Add the Framework Tuesday, September 28, 2010
  • 30. Add the Framework Tuesday, September 28, 2010
  • 31. Add the Framework Tuesday, September 28, 2010
  • 32. Add the Framework Tuesday, September 28, 2010
  • 33. SQLite API - Opening a connection Tuesday, September 28, 2010
  • 34. SQLite API - Opening a connection #import "sqlite3.h" Tuesday, September 28, 2010
  • 35. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; Tuesday, September 28, 2010
  • 36. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); Tuesday, September 28, 2010
  • 37. SQLite API - Opening a connection #import "sqlite3.h" sqlite3 *db; int result = sqlite3_open(PATH, &db); if (result != SQLITE_OK) { Tuesday, September 28, 2010
  • 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" Tuesday, September 28, 2010
  • 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]; Tuesday, September 28, 2010
  • 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]; } Tuesday, September 28, 2010
  • 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 Tuesday, September 28, 2010
  • 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); Tuesday, September 28, 2010
  • 43. SQLite API - executing queries Tuesday, September 28, 2010
  • 44. SQLite API - executing queries int sqlite3_exec( Tuesday, September 28, 2010
  • 45. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, Tuesday, September 28, 2010
  • 46. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, Tuesday, September 28, 2010
  • 47. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, Tuesday, September 28, 2010
  • 48. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, Tuesday, September 28, 2010
  • 49. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage Tuesday, September 28, 2010
  • 50. SQLite API - executing queries int sqlite3_exec( sqlite3 *db, char *sql, int (*callback)(void *, int, char**, char**) callbackFunc, void *context, char **errorMessage ); Tuesday, September 28, 2010
  • 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 Tuesday, September 28, 2010
  • 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, Tuesday, September 28, 2010
  • 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, Tuesday, September 28, 2010
  • 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, Tuesday, September 28, 2010
  • 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); Tuesday, September 28, 2010
  • 56. SQLite API - Prepared Statements More Powerful Unfortunately much more code! Tuesday, September 28, 2010
  • 58. SQLite API-Prepared Statements sqlite3 *db; Tuesday, September 28, 2010
  • 59. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); Tuesday, September 28, 2010
  • 60. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { Tuesday, September 28, 2010
  • 61. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error Tuesday, September 28, 2010
  • 62. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } Tuesday, September 28, 2010
  • 63. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } Tuesday, September 28, 2010
  • 64. SQLite API-Prepared Statements sqlite3 *db; int result = sqlite3_open(DB_PATH, &db); if(result != SQLITE_OK) { //handle error } sqlite3_stmt *stmt; Tuesday, September 28, 2010
  • 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); Tuesday, September 28, 2010
  • 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) { Tuesday, September 28, 2010
  • 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 Tuesday, September 28, 2010
  • 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 } Tuesday, September 28, 2010
  • 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 } //... Tuesday, September 28, 2010
  • 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 } //... Tuesday, September 28, 2010
  • 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 } //... Tuesday, September 28, 2010
  • 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 } //... Tuesday, September 28, 2010
  • 74. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) Tuesday, September 28, 2010
  • 75. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //PARAMETERS HAVE A 1-BASED INDEX! Tuesday, September 28, 2010
  • 76. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); Tuesday, September 28, 2010
  • 77. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); Tuesday, September 28, 2010
  • 78. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //PARAMETERS HAVE A 1-BASED INDEX! sqlite3_bind_int(stmt, 1 /* idx */, 5); sqlite3_bind_text(stmt, 2 /* idx */,"value", -1, SQLITE_TRANSIENT); Tuesday, September 28, 2010
  • 79. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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); Tuesday, September 28, 2010
  • 80. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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) Tuesday, September 28, 2010
  • 81. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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! Tuesday, September 28, 2010
  • 82. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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! Tuesday, September 28, 2010
  • 83. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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]; Tuesday, September 28, 2010
  • 84. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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) { Tuesday, September 28, 2010
  • 85. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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]; Tuesday, September 28, 2010
  • 86. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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]; Tuesday, September 28, 2010
  • 87. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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]; Tuesday, September 28, 2010
  • 88. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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]; Tuesday, September 28, 2010
  • 89. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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); Tuesday, September 28, 2010
  • 90. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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); } Tuesday, September 28, 2010
  • 91. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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); Tuesday, September 28, 2010
  • 92. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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); Tuesday, September 28, 2010
  • 93. SQLite API-Prepared Statements //INSERT INTO CARS(year, make) VALUES(?, ?) //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; Tuesday, September 28, 2010
  • 95. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement: (sqlite3_stmt*)stmt { Tuesday, September 28, 2010
  • 96. SQLite API-Prepared Statements -(void)processRow:(NSMutableDictionary *)row forStatement: (sqlite3_stmt*)stmt { int columnCount = sqlite3_column_count(stmt); Tuesday, September 28, 2010
  • 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++) { Tuesday, September 28, 2010
  • 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! Tuesday, September 28, 2010
  • 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); Tuesday, September 28, 2010
  • 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); Tuesday, September 28, 2010
  • 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]; Tuesday, September 28, 2010
  • 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) { Tuesday, September 28, 2010
  • 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)]; Tuesday, September 28, 2010
  • 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) { Tuesday, September 28, 2010
  • 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); Tuesday, September 28, 2010
  • 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]; Tuesday, September 28, 2010
  • 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 { Tuesday, September 28, 2010
  • 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 Tuesday, September 28, 2010
  • 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 } Tuesday, September 28, 2010
  • 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: Tuesday, September 28, 2010
  • 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]]; Tuesday, September 28, 2010
  • 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]]; } Tuesday, September 28, 2010
  • 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]]; } } Tuesday, September 28, 2010
  • 114. FMDB http://github.com/ccgus/fmdb Tuesday, September 28, 2010
  • 116. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; Tuesday, September 28, 2010
  • 117. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open]) Tuesday, September 28, 2010
  • 118. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db."); Tuesday, September 28, 2010
  • 119. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"]; Tuesday, September 28, 2010
  • 120. FMDB Usage   FMDatabase* db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];   if (![db open])      NSLog(@"Could not open db.");   [db executeUpdate:@"blah blah blah"];      Tuesday, September 28, 2010
  • 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]) Tuesday, September 28, 2010
  • 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], Tuesday, September 28, 2010
  • 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]); Tuesday, September 28, 2010
  • 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)"]; Tuesday, September 28, 2010
  • 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]; Tuesday, September 28, 2010
  • 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; Tuesday, September 28, 2010
  • 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) { Tuesday, September 28, 2010
  • 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 (?, ?)" , Tuesday, September 28, 2010
  • 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! Tuesday, September 28, 2010
  • 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]]; Tuesday, September 28, 2010
  • 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]];   } Tuesday, September 28, 2010
  • 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]; Tuesday, September 28, 2010
  • 133. What about updates? Database is never copied over again If we did, your customers would lose data Tuesday, September 28, 2010
  • 134. Migrations Concept from Ruby on Rails Evolutionary database design Each database has a "version" App runs all migrations to the latest version Tuesday, September 28, 2010
  • 135. Migrations number name 1 initial_schema 2 update_foo 3 implement_blah Tuesday, September 28, 2010
  • 136. Migrations number name 1 initial_schema 2 update_foo 3 implement_blah Tuesday, September 28, 2010
  • 137. Hand-rolled Database Migrator DEMO Tuesday, September 28, 2010
  • 138. FMDB Migration Manager http://github.com/mocra/fmdb- migration-manager Tuesday, September 28, 2010
  • 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]; Tuesday, September 28, 2010
  • 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 Tuesday, September 28, 2010
  • 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} Tuesday, September 28, 2010
  • 142. Aptiva's ActiveRecord http://github.com/aptiva/activerecord (YMMV) Tuesday, September 28, 2010