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

Schema creation not working in Swift 4.1 #109

Open
vccabral opened this issue Aug 15, 2018 · 4 comments
Open

Schema creation not working in Swift 4.1 #109

vccabral opened this issue Aug 15, 2018 · 4 comments

Comments

@vccabral
Copy link

I am attempting to use SharkORM with Swift 4.1 and the table are not being created automatically.

@editfmah
Copy link
Owner

So, if you place a breakpoint on the +(void)initialize method, you should see one for every object. Form your previous issues, it could be that the delegate is being set after opening the database?

@vccabral
Copy link
Author

vccabral commented Aug 15, 2018

This is inside my App delegate.

SharkORM.setDelegate(self)
SharkORM.openDatabaseNamed("dbname")

@alldritt
Copy link
Contributor

alldritt commented Nov 7, 2018

I'm running into the very same issue. After some sleuthing, I've found that the code in -[SharkSchemaManager refactorDatabase:(NSString*)database entity:(NSString*)entity] is failing if it is called before the database is opened.

This happens with Swift because some Swift objects are initialized before the app's AppDelegate is given a chance to open the Shark database in it's init method. refactorDatabase is designed to handle this situation, but it fails. When SharkORM.openDatabaseNamed is called and invokes refactorDatabase to define entities discovered previously, the tests for a nil database fail and cause refactorDatabase to return prematurely.

Changing refectorDatabase to this corrects the problem:

- (void)refactorDatabase:(NSString*)database entity:(NSString*)entity {
    
    if (!database || [database isEqualToString:@""]) {
        
        // this is blank, so grab the default
        
        if (SRKGlobals.sharedObject.defaultDatabaseName != nil) {
            database = SRKGlobals.sharedObject.defaultDatabaseName;
        }
        
        // see if this database has been opened
        if ([SRKGlobals.sharedObject handleForName:database] == nil) {
            // this database will be refactored when finally opened in teh future.
            return;
        }
        
    } // database != nil
    
    // check to see if this table already exists
    if (databases[entity] == nil) {
        
        if ([entity isEqualToString:@"SmallPerson"]) {
            int i=0;
        }
        
        // completely new table, so we can do this in a single operation
        NSString* sql = @"CREATE TABLE IF NOT EXISTS ";
        sql = [sql stringByAppendingString:entity];
        sql = [sql stringByAppendingString:@" (Id "];
        if ([self schemaPrimaryKeyTypeForEntity:entity] == SRK_PROPERTY_TYPE_NUMBER) {
            sql = [sql stringByAppendingString:@"INTEGER PRIMARY KEY AUTOINCREMENT);"];
        } else {
            sql = [sql stringByAppendingString:@"TEXT PRIMARY KEY);"];
        }
        
        [SharkORM executeSQL:sql inDatabase:database];
        
        // now add the columns in one-by-one
        for (NSString* f in [self schemaPropertiesForEntity:entity]) {
            sql = @"ALTER TABLE ";
            sql = [sql stringByAppendingString:entity];
            sql = [sql stringByAppendingString:@" ADD COLUMN "];
            sql = [sql stringByAppendingString:f];
            sql = [sql stringByAppendingString:@" "];
            sql = [sql stringByAppendingString:[self sqlTextTypeFromColumnType:[self entityTypeToSQLSotrageType:[self schemaPropertyType:entity property:f]]]];
            [SharkORM executeSQL:sql inDatabase:database];
        }
        
    } else {
        
        NSString* sql = @"";
        
        // existing table, so look for missing columns and add them
        for (NSString* f in [self schemaPropertiesForEntity:entity]) {
            if (![self databasePropertyExistsInEntity:entity property:f]) {
                sql = @"ALTER TABLE ";
                sql = [sql stringByAppendingString:entity];
                sql = [sql stringByAppendingString:@" ADD COLUMN "];
                sql = [sql stringByAppendingString:f];
                sql = [sql stringByAppendingString:@" "];
                sql = [sql stringByAppendingString:[self sqlTextTypeFromColumnType:[self entityTypeToSQLSotrageType:[self schemaPropertyType:entity property:f]]]];
                [SharkORM executeSQL:sql inDatabase:database];
            }
        }
        
        // look for changed data value types
        for (NSString* f in [self schemaPropertiesForEntity:entity]) {
            if ([self databasePropertyExistsInEntity:entity property:f]) {
                if ([self entityTypeToSQLSotrageType:[self schemaPropertyType:entity property:f]] != [self databasePropertyTypeForEntity:entity property:f]) {
                    
                    // detect change, and migrate data accordingly
                    
                }
            }
        }
        
        // notify the entity class that we are between two states, all new columns have been added, but we have not removed the old ones yet.
        //TODO: implement migration
        
        // look for extra columns that need to be dropped
        BOOL foundDefuncColumns = NO;
        for (NSString* f in [self databasePropertiesForEntity:entity]) {
            if (![self schemaPropertyExists:entity property:f]) {
                foundDefuncColumns = YES;
            }
        }
        
        if (foundDefuncColumns) {
            
            // rename the old table
            [SharkORM executeSQL:[NSString stringWithFormat:@"ALTER TABLE %@ RENAME TO temp_%@;", entity, entity] inDatabase:database];
            
            // completely new table, so we can do this in a single operation
            NSString* sql = @"CREATE TABLE IF NOT EXISTS ";
            sql = [sql stringByAppendingString:entity];
            sql = [sql stringByAppendingString:@" (Id "];
            if ([self schemaPrimaryKeyTypeForEntity:entity] == SRK_PROPERTY_TYPE_NUMBER) {
                sql = [sql stringByAppendingString:@"INTEGER PRIMARY KEY AUTOINCREMENT);"];
            } else {
                sql = [sql stringByAppendingString:@"TEXT PRIMARY KEY);"];
            }
            
            [SharkORM executeSQL:sql inDatabase:database];
            
            // now add the columns in one-by-one
            for (NSString* f in [self schemaPropertiesForEntity:entity]) {
                sql = @"ALTER TABLE ";
                sql = [sql stringByAppendingString:entity];
                sql = [sql stringByAppendingString:@" ADD COLUMN "];
                sql = [sql stringByAppendingString:[self sqlTextTypeFromColumnType:[self entityTypeToSQLSotrageType:[self schemaPropertyType:entity property:f]]]];
                [SharkORM executeSQL:sql inDatabase:database];
            }
            
            // copy the data from the temp database
            [SharkORM executeSQL:[NSString stringWithFormat:@"INSERT INTO %@ (%@) SELECT %@ FROM temp_%@;", entity, [[self schemaPropertiesForEntity:entity] componentsJoinedByString:@","], [[self schemaPropertiesForEntity:entity] componentsJoinedByString:@","], entity] inDatabase:database];
            
            // drop the temp table
            [SharkORM executeSQL:[NSString stringWithFormat:@"DROP TABLE temp_%@;", entity] inDatabase:database];
            
            // clear out the indexes as they are no longer on this new table
            databases[entity].indexes = [NSMutableDictionary new];
            
        }

    }
    
    // now create and remove indexes on the tables
    NSDictionary<NSString*, NSString*>* idx = [self schemaIndexDefinitionsForEntity:entity];
    for (NSString* i in idx.allKeys) {
        if ([self databaseIndexDefinitionsForEntity:entity][i] == nil) {
            // missing index, create it now
            [SharkORM executeSQL:idx[i] inDatabase:database];
        }
    }
    
    // remove old indexes
    idx = [self databaseIndexDefinitionsForEntity:entity];
    for (NSString* i in idx.allKeys) {
        if ([self schemaIndexDefinitionsForEntity:entity][i] == nil) {
            // missing index, create it now
            [SharkORM executeSQL:[NSString stringWithFormat:@"DROP INDEX IF EXISTS %@;", i] inDatabase:database];
        }
    }
    
}

alldritt added a commit to alldritt/sharkorm that referenced this issue Nov 7, 2018
@editfmah
Copy link
Owner

editfmah commented Nov 7, 2018

great I have another fix for the code above even, where new columns don't get created properly. I'll bring it all together and do a release tomorrow.

Thanks @alldritt

alldritt added a commit to alldritt/sharkorm that referenced this issue Nov 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants