SQLite Techniques
SQLite is....

Single-user

File-based

Simple

Cross Platform

A subset of full ANSI SQL
SQLite API


Pure C API

Lots of strange-looking, hard to
debug code

Best choice is to abstract it away
SQLite Tools



SQLite Manager Add-in for Firefox

sqlite3 command line utility
Writable Databases


Your app bundle is signed!

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




Your App Bundle


       Resources
                   Documents
Your App Sandbox




Your App Bundle


       Resources
                   Documents
Creating the
  database
Getting Resource
      Paths
Getting Resource
                Paths

//fetches
path
for
foo.db
Getting Resource
                Paths

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

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








...
Getting Resource
                Paths

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








...
Finding the Documents
      Directory
Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(

Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























N...
Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























N...
Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























N...
Finding the Documents
      Directory

NSArray
*paths
=
NSSearchPathForDirectoriesInDomains(




























N...
Copy a default
database on startup
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
Copy a default
     database on startup
  //in applicationDidFinishLaunching

  NSString *sourcePath = [[NSBundle mainBund...
SQLite API Basics
Add the Framework
Add the Framework
Add the Framework
Add the Framework
SQLite API -
Opening a connection
SQLite API -
    Opening a connection
#import "sqlite3.h"
SQLite API -
    Opening a connection
#import "sqlite3.h"

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

sqlite3 *db;

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

sqlite3 *db;

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

sqlite3 *db;

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

sqlite3 *db;

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

sqlite3 *db;

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

sqlite3 *db;

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

sqlite3 *db;

int result = sqlite3_open(PATH, &db);
if (result ...
SQLite API -
executing queries
SQLite API -
         executing queries
int sqlite3_exec(
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
         executing queries
int sqlite3_exec(
     sqlite3 *db,
     char *sql,
     int (*callback)(void *, i...
SQLite API -
 Prepared Statements


More Powerful

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


sqlite3 *db;
SQLite API-Prepared Statements


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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


-(void)processRow:(NSMutableDictionary *)row forStatement:(sqlite3_stmt*)stmt {
 int colu...
FMDB


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


Database is never copied over again

If we did, your customers would lose
data
Migrations

Concept from Ruby on Rails

Evolutionary database design

Each database has a "version"

App runs all migratio...
Migrations

number        name
  1      initial_schema
  2        update_foo
  3      implement_blah
Migrations

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


 DEMO
FMDB Migration
       Manager


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

NSArray *migrations = [NSArray arrayWithObjects:
     [CreateStudents migration]...
FMDB Migration
                      Manager
@interface CreateStudents : FmdbMigration
{
}
@end

@implementation CreateStu...
ActiveRecord

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

[p save];




Person *p =...
Aptiva's ActiveRecord


 http://github.com/aptiva/activerecord




                (YMMV)
Questions?
Upcoming SlideShare
Loading in...5
×

SQLite Techniques

1,389

Published on

Presentation given at the Houston iPhone Developers Meetup on the september mee

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,389
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
65
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide



































































































































  • Transcript of "SQLite Techniques"

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




























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




























pathForResource:@"foo" 




























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

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


























NSDocumentDirectory,

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


























NSDocumentDirectory,
 


























NSUserDomainMask,

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


























NSDocumentDirectory,
 


























NSUserDomainMask,
 


























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


























NSDocumentDirectory,
 


























NSUserDomainMask,
 


























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

      Clipping is a handy way to collect important slides you want to go back to later.

    ×