diff --git a/Classes/FmdbMigration.h b/Classes/FmdbMigration.h index d0e4802..0b322e7 100644 --- a/Classes/FmdbMigration.h +++ b/Classes/FmdbMigration.h @@ -25,12 +25,21 @@ - (void)createTable:(NSString *)tableName; - (void)createTable:(NSString *)tableName withColumns:(NSArray *)columns; + +- (void)createIndex:(NSString *)indexName onTable:(NSString *)tableName withColumns:(NSArray *)columns; + +- (void)createTable:(NSString *)tableName withColumns:(NSArray *)columns andPrimaryKeys:(NSArray *)keyNames; - (void)dropTable:(NSString *)tableName; +- (void)dropIndex:(NSString *)indexName; + - (void)addColumn:(FmdbMigrationColumn *)column forTableName:(NSString *)tableName; +- (void)dropColumn:(FmdbMigrationColumn *)column forTableName:(NSString *)tableName; + // This init method exists for the purposes of unit testing. // Production code should never call this method, instead instantiate // your subclasses with +migration method. - (id)initWithDatabase:(FMDatabase *)db; + @end diff --git a/Classes/FmdbMigration.m b/Classes/FmdbMigration.m index 33253d1..5f9e3d5 100644 --- a/Classes/FmdbMigration.m +++ b/Classes/FmdbMigration.m @@ -10,62 +10,95 @@ @implementation FmdbMigration -@synthesize db=db_; +@synthesize db = db_; + (id)migration { - return [[[self alloc] init] autorelease]; + return [[[self alloc] init] autorelease]; } #pragma mark - #pragma mark up/down methods -- (void)up -{ - NSLog([NSString stringWithFormat:@"%s: -up method not implemented", NSStringFromClass([self class])]); +- (void)up { + NSLog([NSString stringWithFormat:@"%@: -up method not implemented", NSStringFromClass([self class])]); } -- (void)down -{ - NSLog([NSString stringWithFormat:@"%s: -down method not implemented", NSStringFromClass([self class])]); +- (void)down { + NSLog([NSString stringWithFormat:@"%@: -down method not implemented", NSStringFromClass([self class])]); } -- (void)upWithDatabase:(FMDatabase *)db -{ - self.db = db; - [self up]; +- (void)upWithDatabase:(FMDatabase *)db { + self.db = db; + [self up]; } -- (void)downWithDatabase:(FMDatabase *)db -{ - self.db = db; - [self down]; + +- (void)downWithDatabase:(FMDatabase *)db { + self.db = db; + [self down]; } #pragma mark - #pragma mark Helper methods for manipulating database schema -- (void)createTable:(NSString *)tableName withColumns:(NSArray *)columns -{ - [self createTable:tableName]; - for (FmdbMigrationColumn *migrationColumn in columns) { - [self addColumn:migrationColumn forTableName:tableName]; - } +- (void)createTable:(NSString *)tableName withColumns:(NSArray *)columns { + NSMutableArray *columnDefinitions = [[NSMutableArray alloc] initWithCapacity:10]; + [columnDefinitions addObject:@"id integer primary key autoincrement"]; + for (FmdbMigrationColumn *migrationColumn in columns) { + [columnDefinitions addObject:[migrationColumn sqlDefinition]]; + } + + NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@)", tableName, [columnDefinitions componentsJoinedByString:@","]]; + [db_ executeUpdate:sql]; } -- (void)createTable:(NSString *)tableName -{ - NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (id integer primary key autoincrement)", tableName]; - [db_ executeUpdate:sql]; +- (void)createIndex:(NSString *)indexName + onTable:(NSString *)tableName + withColumns:(NSArray *)columns { + NSString *indexColumns = [columns componentsJoinedByString:@","]; + NSString *sql = [NSString stringWithFormat:@"CREATE INDEX IF NOT EXISTS %@ ON %@ (%@);", + indexName, + tableName, + indexColumns]; + [db_ executeUpdate:sql]; } -- (void)dropTable:(NSString *)tableName -{ - NSString *sql = [NSString stringWithFormat:@"DROP TABLE IF EXISTS %@", tableName]; - [db_ executeUpdate:sql]; +- (void)createTable:(NSString *)tableName + withColumns:(NSArray *)columns + andPrimaryKeys:(NSArray *)keyNames { + NSMutableArray *columnDefinitions = [[NSMutableArray alloc] initWithCapacity:[columns count]]; + for (FmdbMigrationColumn *migrationColumn in columns) { + [columnDefinitions addObject:[migrationColumn sqlDefinition]]; + } + + NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (%@, primary key (%@))", + tableName, + [columnDefinitions componentsJoinedByString:@","], + [keyNames componentsJoinedByString:@","]]; + [db_ executeUpdate:sql]; } -- (void)addColumn:(FmdbMigrationColumn *)column forTableName:(NSString *)tableName -{ - NSString *sql = [NSString stringWithFormat:@"ALTER TABLE %@ ADD COLUMN %@", tableName, [column sqlDefinition]]; +- (void)createTable:(NSString *)tableName { + NSString *sql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@ (id integer primary key autoincrement)", tableName]; + [db_ executeUpdate:sql]; +} + +- (void)dropTable:(NSString *)tableName { + NSString *sql = [NSString stringWithFormat:@"DROP TABLE IF EXISTS %@", tableName]; + [db_ executeUpdate:sql]; +} + +- (void)dropIndex:(NSString *)indexName { + NSString *sql = [NSString stringWithFormat:@"DROP INDEX IF EXISTS %@", indexName]; + [db_ executeUpdate:sql]; +} + +- (void)addColumn:(FmdbMigrationColumn *)column forTableName:(NSString *)tableName { + NSString *sql = [NSString stringWithFormat:@"ALTER TABLE %@ ADD COLUMN %@", tableName, [column sqlDefinition]]; + [db_ executeUpdate:sql]; +} + +- (void)dropColumn:(NSString *)columnName forTableName:(NSString *)tableName { + NSString *sql = [NSString stringWithFormat:@"ALTER TABLE %@ DROP COLUMN %@", tableName, columnName]; [db_ executeUpdate:sql]; } @@ -73,20 +106,18 @@ - (void)addColumn:(FmdbMigrationColumn *)column forTableName:(NSString *)tableNa #pragma mark - #pragma mark Unit testing helpers -- (id)initWithDatabase:(FMDatabase *)db -{ - if ([super init]) { - self.db = db; - return self; - } - return nil; +- (id)initWithDatabase:(FMDatabase *)db { + if ([super init]) { + self.db = db; + return self; + } + return nil; } -- (void)dealloc -{ - [db_ release]; - - [super dealloc]; +- (void)dealloc { + [db_ release]; + + [super dealloc]; } diff --git a/Classes/FmdbMigrationColumn.h b/Classes/FmdbMigrationColumn.h index f1f31db..57019b3 100644 --- a/Classes/FmdbMigrationColumn.h +++ b/Classes/FmdbMigrationColumn.h @@ -16,6 +16,7 @@ } @property (retain) NSString *columnName; @property (retain) NSString *columnType; +@property BOOL allowNulls; @property (retain) id defaultValue; + (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName @@ -23,6 +24,13 @@ + (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName columnType:(NSString*)columnType defaultValue:(id)defaultValue; ++ (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName + columnType:(NSString*)columnType + defaultValue:(id)defaultValue + allowNulls:(BOOL)allowNulls; ++ (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName + columnType:(NSString*)columnType + allowNulls:(BOOL)allowNulls; // Used for sql queries "ALTER TABLE table_name ADD COLUMN [column sqlDefinition]" - (NSString *)sqlDefinition; diff --git a/Classes/FmdbMigrationColumn.m b/Classes/FmdbMigrationColumn.m index f246dc2..66ee65b 100644 --- a/Classes/FmdbMigrationColumn.m +++ b/Classes/FmdbMigrationColumn.m @@ -10,7 +10,7 @@ @implementation FmdbMigrationColumn -@synthesize columnName=columnName_, columnType=columnType_, defaultValue=defaultValue_; +@synthesize columnName=columnName_, columnType=columnType_, defaultValue=defaultValue_, allowNulls=allowNulls_; #pragma mark - #pragma mark Constructor helpers @@ -34,6 +34,36 @@ + (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName return column; } ++ (FmdbMigrationColumn *)columnWithColumnName:(NSString *)columnName + columnType:(NSString *)columnType + defaultValue:(id)defaultValue + allowNulls:(BOOL)allowNulls +{ + FmdbMigrationColumn* column = [self columnWithColumnName:columnName columnType:columnType defaultValue:defaultValue]; + column.allowNulls = allowNulls; + return column; +} + ++ (FmdbMigrationColumn *)columnWithColumnName:(NSString *)columnName + columnType:(NSString *)columnType + allowNulls:(BOOL)allowNulls +{ + FmdbMigrationColumn* column = [self columnWithColumnName:columnName columnType:columnType]; + column.allowNulls = allowNulls; + return column; +} + + +- (id)init +{ + self = [super init]; + if (self) { + allowNulls_ = true; + } + + return self; +} + // Notes from http://www.sqlite.org/lang_altertable.html: // Column-def may take any of the forms permissable in a CREATE TABLE statement, with the following restrictions: // * The column may not have a PRIMARY KEY or UNIQUE constraint. @@ -41,7 +71,19 @@ + (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName // * If a NOT NULL constraint is specified, then the column must have a default value other than NULL. - (NSString *)sqlDefinition { - NSString *sql = [NSString stringWithFormat:@"%@ %@", self.columnName, self.columnTypeDefinition]; + NSString *nullString = self.allowNulls ? @"NULL" : @"NOT NULL"; + NSMutableArray *statements = [NSMutableArray arrayWithArray: @[ + self.columnName, + self.columnTypeDefinition, + nullString + ]]; + + if (self.defaultValue) { + [statements addObject:[NSString stringWithFormat:@"default %@", self.defaultValue]]; + } + + NSString *sql = [statements componentsJoinedByString:@" "]; + return sql; } diff --git a/fmdb-migration-manager.xcodeproj/xcuserdata/nimast.xcuserdatad/xcschemes/fmdb-migration-manager.xcscheme b/fmdb-migration-manager.xcodeproj/xcuserdata/nimast.xcuserdatad/xcschemes/fmdb-migration-manager.xcscheme new file mode 100644 index 0000000..4717b97 --- /dev/null +++ b/fmdb-migration-manager.xcodeproj/xcuserdata/nimast.xcuserdatad/xcschemes/fmdb-migration-manager.xcscheme @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fmdb-migration-manager.xcodeproj/xcuserdata/nimast.xcuserdatad/xcschemes/xcschememanagement.plist b/fmdb-migration-manager.xcodeproj/xcuserdata/nimast.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..69a2cc6 --- /dev/null +++ b/fmdb-migration-manager.xcodeproj/xcuserdata/nimast.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + fmdb-migration-manager.xcscheme + + orderHint + 31 + + + SuppressBuildableAutocreation + + D2AAC0C605546C1D00DB518D + + primary + + + + +