Не получать строки из sqlite3 в приложении iOS - PullRequest
0 голосов
/ 21 марта 2011

Следующий код не возвращает строк, но когда я запускаю запрос в sqlite3 в терминале, я получаю ожидаемый результат. Итак, я думаю, здесь есть какая-то тривиальная ошибка:

- (void)initializeDatabaseWithFilter:(NSString *)filter
{
    NSMutableArray *fristArray = [[NSMutableArray alloc] init];
    self.frister = fristArray;
    [fristArray release];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"Frister.sqlite"];
    if (sqlite3_open([path UTF8String], &database) == SQLITE_OK){
        // Get primary key for all entries with filter
        const char *sql = "SELECT fristKey FROM frister WHERE ? = 1";
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) != SQLITE_OK) {
            NSAssert1(0,@"Error: Failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
        }
        sqlite3_bind_text(statement, 1, [filter UTF8String], -1, SQLITE_TRANSIENT);
        NSLog(@"%@",filter); // lets me see if the filter column name is passed to the method.
        int i = 0; // this is to see if I get some rows in return
        while (sqlite3_step(statement) == SQLITE_ROW) {
            i++;
            int primaryKey = sqlite3_column_int(statement,0);
            Frist *td = [[Frist alloc] inithWithOwnerID:primaryKey database:database];

            [frister addObject:td];
            [td release];
        }
        NSLog(@"%d",i); // If I get some results, I should get a number here...
        sqlite3_finalize(statement);
    } else {
        sqlite3_close(database);
        NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
    }
}

Мне бы очень нужна помощь:)

Ответы [ 2 ]

2 голосов
/ 21 марта 2011

Я вижу, что вы уже приняли ответ, но мне кажется, я вижу проблему в вашем вызове sqlite.

В терминале, я полагаю, вы делаете запрос примерно так:

SELECT fristKey FROM frister WHERE column = 1

Но ваш код не делает эквивалентный запрос. Вместо этого он выполняет такой запрос:

SELECT fristKey FROM frister WHERE 'column' = 1

Поскольку строка "column" никогда не будет равна 1, ваш запрос не даст никаких результатов. Вы не можете привязать имя столбца к параметризованному запросу, только литеральное значение.

2 голосов
/ 21 марта 2011

(добавив это в качестве ответа, поскольку было бы довольно громоздко поместить его в качестве комментария)

Я настоятельно рекомендую использовать FMDB для взаимодействия с базой данных.Это обертка вокруг SQLite C API, которая позволяет очень легко взаимодействовать с базой данных.Ваш код можно изменить, чтобы использовать его с минимальным вмешательством.Вот как это будет выглядеть:

- (void)initializeDatabaseWithFilter:(NSString *)filter
{
    self.frister = [NSMutableArray array];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"Frister.sqlite"];

    FMDatabase *db = [FMDatabase databaseWithPath:path];
    if ([db open]) {
        NSString *sql = [NSString stringWithFormat:@"SELECT fristKey FROM frister WHERE %@ = 1", filter];
        FMResultSet *results = [db executeQuery:sql];
        while([results next]) {
            int primaryKey = [results intForColumn:@"fristKey"];
            Frist *td = [[Frist alloc] initWithOwnerID:primaryKey database:db];
            [[self frister] addObject:td];
            [td release];
        }
        [db close];
    }
}

Разве это не выглядит TON более читабельным?Довольно легко увидеть, что вы выполняете запрос, просматриваете результаты и вытягиваете «fristKey», чтобы создать объект «Frist».Вам не нужно беспокоиться о sqlite3_open, подготовке операторов, привязке параметров или завершении операторов.

Другая вещь, которую вам нужно изменить, - это Frist объект: он должен принять FMDatabase* как «база данных» вместо sqlite3*.Вы также можете рассмотреть возможность открытия базы данных один раз, а затем оставить ее открытой до тех пор, пока она вам больше не понадобится (в противном случае вам придется -open делать это каждый раз, когда вы захотите выполнить что-то; это полностью ваше дело).

Чтобы включить FMDB в ваше приложение, загрузите код с Github, а затем скопируйте файлы FMDatabase, FMDatabaseAdditions и FMResultSet (все 6) в свое приложение и #import их, где вам нужно будет взаимодействовать сбаза данных.Вам все равно нужно будет ссылаться на sqlite3.dylib.

Просто убедитесь, что вы соблюдаете (очень разрешительную) лицензию .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...