Index: src/SL3PreparedStatement.h ================================================================== --- src/SL3PreparedStatement.h +++ src/SL3PreparedStatement.h @@ -39,10 +39,13 @@ - (void)bindWithArray: (OFArray *)array; - (void)bindWithDictionary: (OFDictionary OF_GENERIC(OFString *, id) *)dictionary; - (void)clearBindings; -- (void)step; +- (id)objectForColumn: (size_t)column; +- (size_t)columnCount; +- (OFString *)nameForColumn: (size_t)column; +- (bool)step; - (void)reset; @end OF_ASSUME_NONNULL_END Index: src/SL3PreparedStatement.m ================================================================== --- src/SL3PreparedStatement.m +++ src/SL3PreparedStatement.m @@ -159,18 +159,64 @@ @throw [SL3ClearBindingsFailedException exceptionWithStatement: self errorCode: code]; } -- (void)step +- (bool)step { int code = sqlite3_step(_stmt); if (code != SQLITE_DONE && code != SQLITE_ROW) @throw [SL3ExecuteStatementFailedException exceptionWithStatement: self errorCode: code]; + + return (code == SQLITE_ROW); +} + +- (id)objectForColumn: (size_t)column +{ + if (column > INT_MAX) + @throw [OFOutOfRangeException exception]; + + switch (sqlite3_column_type(_stmt, column)) { + case SQLITE_INTEGER: + return [OFNumber numberWithLongLong: + sqlite3_column_int64(_stmt, column)]; + case SQLITE_FLOAT: + return [OFNumber numberWithDouble: + sqlite3_column_double(_stmt, column)]; + case SQLITE_TEXT: + return [OFString stringWithUTF8String: + (const char *)sqlite3_column_text(_stmt, column)]; + case SQLITE_BLOB: + return [OFData + dataWithItems: sqlite3_column_blob(_stmt, column) + count: sqlite3_column_bytes(_stmt, column)]; + case SQLITE_NULL: + return [OFNull null]; + default: + OF_ENSURE(0); + } +} + +- (size_t)columnCount +{ + return sqlite3_column_count(_stmt); +} + +- (OFString *)nameForColumn: (size_t)column +{ + const char *name; + + if (column > [self columnCount]) + @throw [OFOutOfRangeException exception]; + + if ((name = sqlite3_column_name(_stmt, column)) == NULL) + @throw [OFOutOfMemoryException exception]; + + return [OFString stringWithUTF8String: name]; } - (void)reset { int code = sqlite3_reset(_stmt); Index: tests/Tests.m ================================================================== --- tests/Tests.m +++ tests/Tests.m @@ -61,9 +61,40 @@ @"$b", @"Test", @"$c", [OFData dataWithItems: "xyz" count: 3], nil]]; [stmt step]; + + stmt = [conn prepareStatement: @"SELECT * FROM test"]; + for (size_t i = 0; [stmt step]; i++) { + OF_ENSURE([stmt columnCount] == 3); + OF_ENSURE([[stmt nameForColumn: 0] isEqual: @"a"]); + OF_ENSURE([[stmt nameForColumn: 1] isEqual: @"b"]); + OF_ENSURE([[stmt nameForColumn: 2] isEqual: @"c"]); + + switch (i) { + case 0: + OF_ENSURE([[stmt objectForColumn: 0] + isEqual: [OFNumber numberWithInt: 5]]); + OF_ENSURE([[stmt objectForColumn: 1] + isEqual: @"String"]); + OF_ENSURE([[stmt objectForColumn: 2] + isEqual: [OFData dataWithItems: "abc" + count: 3]]); + break; + case 1: + OF_ENSURE([[stmt objectForColumn: 0] + isEqual: [OFNumber numberWithInt: 7]]); + OF_ENSURE([[stmt objectForColumn: 1] + isEqual: @"Test"]); + OF_ENSURE([[stmt objectForColumn: 2] + isEqual: [OFData dataWithItems: "xyz" + count: 3]]); + break; + default: + OF_ENSURE(0); + } + } [OFApplication terminate]; } @end