且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在我的iOS项目中添加和执行.sql文件?

更新时间:2023-09-25 07:59:10

我执行脚本作为iOS项目的一部分。我这样做的原因是创建数据库模式的同一系列脚本也更新数据库模式(在发布后,运行新的增量脚本以向前拉模式)。这里详细解释:

I execute scripts as part of an iOS project. The reason I do it is the same series of scripts that creates the database schema also updates the database schema (after release, new delta scripts are run to pull the schema forward). It's explained in detail here:

SQLITE与Android(设置数据库的***方法)

我将脚本添加为资源,然后执行它。有一些EXxxx日志调用,但在其他方面通用。注意,tail-sqlite的使用在脚本循环时执行一个语句,尾部作为它停止的标记。这里是我用来执行的函数:

I add the script as a resource in the project and then execute it. There's some EXxxx logging calls but otherwise generic. Note the use of tail - sqlite executes a statement at a time of the script looping through with tail as a marker where it left off. Here's the function I use to execute:

- (BOOL)executeScript:(NSString *)contents error:(NSError **)error
{
    ENHeading(@"executeScript");

    sqlite3_stmt *stmt = NULL;
    const char *zTail;
    int rc;

    zTail = [contents UTF8String];

    while(zTail != NULL && 0 < strlen(zTail)) 
    {
        ENDebug("zTail: \"%s\"\n", zTail);

        NSString *tailStr = [NSString stringWithUTF8String:zTail];
        NSString *trimmed = [tailStr stringByTrimmingCharactersInSet:
                             [NSCharacterSet whitespaceAndNewlineCharacterSet]];

        if ([trimmed length] == 0)
        {
            ENInfo("ignoring trailing whitespace");
            break;
        }

        // Temporarily hold this until the end of the loop in case we need to report an error
        const char *newzTail;

        rc = sqlite3_prepare_v2(_sqlite3, zTail, -1, &stmt, &newzTail);
        if(SQLITE_OK != rc) 
        {
            ENError(@"prepare err:%@", [self errorMessage]);
            if (error != NULL) {
                *error = [[[ENSqliteError alloc] initWithErrorCode:ENSqliteErrorInvalidSql 
                                                            reason:[self errorMessage]] autorelease];
            }

            return NO;
        }

        rc = sqlite3_step(stmt);
        ENDebug(@"rc=%d", rc);
        switch (rc)
        {
            case SQLITE_ROW:
                ENError(@"statement returns rows, script ignores");
                break;

            case SQLITE_OK:
            case SQLITE_DONE:
                break;

            default:
                ENError(@"error");
                ENError(@"prepare err:%@", [self errorMessage]);
                if (error != NULL) {
                    *error = [[[ENSqliteError alloc] initWithErrorCode:ENSqliteErrorReadingRows 
                                                                reason:[self errorMessage]] autorelease];
                }

                return NO;
        }

        // For next time around the loop
        zTail = newzTail;

        // Clear up since we're about to prepare another
        sqlite3_finalize(stmt);
    } 

    return YES;
}