Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add allow nulls and default value to columns. Enable use of constraints and default values in FmdbMigration createTable #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Classes/FmdbMigration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
121 changes: 76 additions & 45 deletions Classes/FmdbMigration.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,83 +10,114 @@


@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];
}


#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];
}


Expand Down
8 changes: 8 additions & 0 deletions Classes/FmdbMigrationColumn.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@
}
@property (retain) NSString *columnName;
@property (retain) NSString *columnType;
@property BOOL allowNulls;
@property (retain) id defaultValue;

+ (FmdbMigrationColumn*)columnWithColumnName:(NSString*)columnName
columnType:(NSString*)columnType;
+ (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;
Expand Down
46 changes: 44 additions & 2 deletions Classes/FmdbMigrationColumn.m
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -34,14 +34,56 @@ + (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.
// * The column may not have a default value of CURRENT_TIME, CURRENT_DATE or CURRENT_TIMESTAMP.
// * 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;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0460"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D2AAC0C605546C1D00DB518D"
BuildableName = "fmdb-migration-manager.dylib"
BlueprintName = "fmdb-migration-manager"
ReferencedContainer = "container:fmdb-migration-manager.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
</Testables>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>fmdb-migration-manager.xcscheme</key>
<dict>
<key>orderHint</key>
<integer>31</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>D2AAC0C605546C1D00DB518D</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
</plist>