From 1f75b90949e63cc419e32235c50247d4b0f44398 Mon Sep 17 00:00:00 2001 From: helge Date: Sun, 20 Feb 2005 20:14:11 +0000 Subject: [PATCH] basic implementation is working now git-svn-id: http://svn.opengroupware.org/SOPE/trunk@577 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-gdl1/SQLite3/ChangeLog | 4 + sope-gdl1/SQLite3/NSData+SQLiteVal.m | 33 +- sope-gdl1/SQLite3/NSNumber+SQLiteVal.m | 87 +---- sope-gdl1/SQLite3/NSString+SQLite.h | 13 +- sope-gdl1/SQLite3/NSString+SQLite.m | 8 +- sope-gdl1/SQLite3/NSString+SQLiteVal.m | 38 +- sope-gdl1/SQLite3/README | 3 +- sope-gdl1/SQLite3/SQLiteChannel+Model.m | 87 +++-- sope-gdl1/SQLite3/SQLiteChannel.h | 5 + sope-gdl1/SQLite3/SQLiteChannel.m | 479 +++++++++++++----------- sope-gdl1/SQLite3/SQLiteContext.m | 4 +- sope-gdl1/SQLite3/SQLiteValues.h | 19 +- sope-gdl1/SQLite3/SQLiteValues.m | 64 ++++ sope-gdl1/SQLite3/Version | 4 +- sope-gdl1/SQLite3/gdltest.m | 211 ++++++----- 15 files changed, 565 insertions(+), 494 deletions(-) diff --git a/sope-gdl1/SQLite3/ChangeLog b/sope-gdl1/SQLite3/ChangeLog index 7a2b9a7c..157a64c9 100644 --- a/sope-gdl1/SQLite3/ChangeLog +++ b/sope-gdl1/SQLite3/ChangeLog @@ -1,3 +1,7 @@ +2005-02-20 Helge Hess + + * most SQL operations based on models are implemented now (v4.5.9) + 2005-02-20 Helge Hess * made gdltest work again diff --git a/sope-gdl1/SQLite3/NSData+SQLiteVal.m b/sope-gdl1/SQLite3/NSData+SQLiteVal.m index ec01f757..a3e044b0 100644 --- a/sope-gdl1/SQLite3/NSData+SQLiteVal.m +++ b/sope-gdl1/SQLite3/NSData+SQLiteVal.m @@ -30,30 +30,17 @@ @implementation NSData(SQLiteValues) -static NSData *EmptyData = nil; - -+ (id)valueFromCString:(const char *)_cstr length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel -{ - if (_length == 0) { - if (EmptyData == nil) EmptyData = [[NSData alloc] init]; - return EmptyData; - } - return [[[self alloc] initWithBytes:_cstr length:_length] autorelease]; +- (id)initWithSQLiteInt:(int)_value { + return [self initWithBytes:&_value length:sizeof(int)]; } - -+ (id)valueFromBytes:(const void *)_bytes length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel -{ - if (_length == 0) { - if (EmptyData == nil) EmptyData = [[NSData alloc] init]; - return EmptyData; - } - return [[[self alloc] initWithBytes:_bytes length:_length] autorelease]; +- (id)initWithSQLiteDouble:(double)_value { + return [self initWithBytes:&_value length:sizeof(double)]; +} +- (id)initWithSQLiteText:(const unsigned char *)_value { + return [self initWithBytes:_value length:strlen(_value)]; +} +- (id)initWithSQLiteData:(const void *)_value length:(int)_length { + return [self initWithBytes:_value length:_length]; } - (NSString *)stringValueForSQLite3Type:(NSString *)_type diff --git a/sope-gdl1/SQLite3/NSNumber+SQLiteVal.m b/sope-gdl1/SQLite3/NSNumber+SQLiteVal.m index fbedbb4c..92118b23 100644 --- a/sope-gdl1/SQLite3/NSNumber+SQLiteVal.m +++ b/sope-gdl1/SQLite3/NSNumber+SQLiteVal.m @@ -29,79 +29,30 @@ @implementation NSNumber(SQLiteValues) -static Class NSNumberClass = Nil; -static NSNumber *yesNum = nil; -static NSNumber *noNum = nil; - -+ (id)valueFromCString:(const char *)_cstr length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel -{ - // TODO: can we avoid the lowercaseString? - unsigned len; - unichar c1; - - if ((len = [_type length]) == 0) - return nil; +- (id)initWithSQLiteInt:(int)_value { + return [self initWithInt:_value]; +} +- (id)initWithSQLiteDouble:(double)_value { + return [self initWithDouble:_value]; +} +- (id)initWithSQLiteText:(const unsigned char *)_value { + return index(_value, '.') != NULL + ? [self initWithDouble:atof(_value)] + : [self initWithInt:atoi(_value)]; +} - if (NSNumberClass == Nil) NSNumberClass = [NSNumber class]; - - c1 = [_type characterAtIndex:0]; - switch (c1) { - case 'f': case 'F': { - if (len < 5) - break; - if ([[_type lowercaseString] hasPrefix:@"float"]) - return [NSNumberClass numberWithDouble:atof(_cstr)]; - break; - } - case 's': case 'S': { - if (len < 8) - break; - if ([[_type lowercaseString] hasPrefix:@"smallint"]) - return [NSNumberClass numberWithShort:atoi(_cstr)]; - break; - } - case 'i': case 'I': { - if (len < 3) - break; - if ([[_type lowercaseString] hasPrefix:@"int"]) - return [NSNumberClass numberWithInt:atoi(_cstr)]; - } - case 'b': case 'B': { - if (len < 4) - break; - if (![[_type lowercaseString] hasPrefix:@"bool"]) - break; - - if (yesNum == nil) yesNum = [[NSNumberClass numberWithBool:YES] retain]; - if (noNum == nil) noNum = [[NSNumberClass numberWithBool:NO] retain]; - - if (_length == 0) - return noNum; - - switch (*_cstr) { - case 't': case 'T': - case 'y': case 'Y': - case '1': - return yesNum; - default: - return noNum; - } - } +- (id)initWithSQLiteData:(const void *)_value length:(int)_length { + switch (_length) { + case 1: return [self initWithUnsignedChar:*(char *)_value]; + case 2: return [self initWithShort:*(short *)_value]; + case 4: return [self initWithInt:*(int *)_value]; + case 8: return [self initWithDouble:*(double *)_value]; } + + [self release]; return nil; } -+ (id)valueFromBytes:(const void *)_bytes length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel -{ - return [self notImplemented:_cmd]; -} - - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute { diff --git a/sope-gdl1/SQLite3/NSString+SQLite.h b/sope-gdl1/SQLite3/NSString+SQLite.h index 4bc327fc..4de73577 100644 --- a/sope-gdl1/SQLite3/NSString+SQLite.h +++ b/sope-gdl1/SQLite3/NSString+SQLite.h @@ -1,7 +1,7 @@ /* NSString+SQLite.h - Copyright (C) 1999 MDlink online service center GmbH and Helge Hess + Copyright (C) 1999-2005 MDlink online service center GmbH and Helge Hess Author: Helge Hess (helge@mdlink.de) @@ -22,7 +22,6 @@ If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id: NSString+SQLite.h,v 1.1 2004/06/14 14:27:44 helge Exp $ #ifndef ___SQLite_NSString_H___ #define ___SQLite_NSString_H___ @@ -31,11 +30,11 @@ @interface NSString(SQLiteMiscStrings) -- (NSString *)_pgModelMakeInstanceVarName; -- (NSString *)_pgModelMakeClassName; -- (NSString *)_pgStringWithCapitalizedFirstChar; -- (NSString *)_pgStripEndSpaces; +- (NSString *)_sqlite3ModelMakeInstanceVarName; +- (NSString *)_sqlite3ModelMakeClassName; +- (NSString *)_sqlite3StringWithCapitalizedFirstChar; +- (NSString *)_sqlite3StripEndSpaces; @end -#endif +#endif /* ___SQLite_NSString_H___ */ diff --git a/sope-gdl1/SQLite3/NSString+SQLite.m b/sope-gdl1/SQLite3/NSString+SQLite.m index 530b2bd8..3d729b38 100644 --- a/sope-gdl1/SQLite3/NSString+SQLite.m +++ b/sope-gdl1/SQLite3/NSString+SQLite.m @@ -34,7 +34,7 @@ @implementation NSString(SQLiteMiscStrings) -- (NSString *)_pgModelMakeInstanceVarName { +- (NSString *)_sqlite3ModelMakeInstanceVarName { if ([self length] == 0) return @""; else { @@ -69,7 +69,7 @@ } } -- (NSString *)_pgModelMakeClassName { +- (NSString *)_sqlite3ModelMakeClassName { if ([self length] == 0) return @""; else { @@ -107,7 +107,7 @@ } } -- (NSString *)_pgStringWithCapitalizedFirstChar { +- (NSString *)_sqlite3StringWithCapitalizedFirstChar { NSCharacterSet *upperSet = [NSCharacterSet uppercaseLetterCharacterSet]; if ([self length] == 0) @@ -124,7 +124,7 @@ } } -- (NSString *)_pgStripEndSpaces { +- (NSString *)_sqlite3StripEndSpaces { if ([self length] > 0) { NSCharacterSet *spaceSet = [NSCharacterSet whitespaceCharacterSet]; NSMutableString *str = [NSMutableString stringWithCapacity:[self length]]; diff --git a/sope-gdl1/SQLite3/NSString+SQLiteVal.m b/sope-gdl1/SQLite3/NSString+SQLiteVal.m index 9e76bcc7..290c9d44 100644 --- a/sope-gdl1/SQLite3/NSString+SQLiteVal.m +++ b/sope-gdl1/SQLite3/NSString+SQLiteVal.m @@ -29,28 +29,30 @@ @implementation NSString(SQLiteValues) -static Class NSStringClass = Nil; -static Class EOExprClass = Nil; +static Class EOExprClass = Nil; -+ (id)valueFromCString:(const char *)_cstr length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel -{ - if (_cstr == NULL) return nil; - if (*_cstr == '\0') return @""; - if (NSStringClass == Nil) NSStringClass = [NSString class]; +- (id)initWithSQLiteInt:(int)_value { + char buf[256]; + sprintf(buf, "%i", _value); + return [self initWithCString:buf]; +} +- (id)initWithSQLiteDouble:(double)_value { + char buf[256]; + sprintf(buf, "%g", _value); + return [self initWithCString:buf]; +} - // TODO: cache IMP of selector - return [NSStringClass stringWithCString:_cstr]; +- (id)initWithSQLiteText:(const unsigned char *)_value { + return [self initWithUTF8String:_value]; } -+ (id)valueFromBytes:(const void *)_bytes length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel -{ - return [self notImplemented:_cmd]; +- (id)initWithSQLiteData:(const void *)_value length:(int)_length { + NSData *d; + + d = [[NSData alloc] initWithBytes:_value length:_length]; + self = [self initWithData:d encoding:NSUTF8StringEncoding]; + [d release]; + return self; } - (NSString *)stringValueForSQLite3Type:(NSString *)_type diff --git a/sope-gdl1/SQLite3/README b/sope-gdl1/SQLite3/README index 6563b139..96673f5f 100644 --- a/sope-gdl1/SQLite3/README +++ b/sope-gdl1/SQLite3/README @@ -5,11 +5,12 @@ Note: this is far from being complete! The adaptor is currently a fork of TODO ==== -- rename methods with 'pg' in the name - check EOAttribute+SQLite: -loadValueClassAndTypeUsingSQLiteType:... - SQLiteChannel.m: -primaryFetchAttributes => check field name processing +- rewrite for exception less operation +- implement more methods in SQLiteChannel+Model (hard with SQLite though) Basics ====== diff --git a/sope-gdl1/SQLite3/SQLiteChannel+Model.m b/sope-gdl1/SQLite3/SQLiteChannel+Model.m index a3b26401..1932633b 100644 --- a/sope-gdl1/SQLite3/SQLiteChannel+Model.m +++ b/sope-gdl1/SQLite3/SQLiteChannel+Model.m @@ -1,7 +1,7 @@ /* SQLiteChannel+Model.m - Copyright (C) 2003 SKYRIX Software AG + Copyright (C) 2003-2005 SKYRIX Software AG Author: Helge Hess (helge.hess@skyrix.com) @@ -22,12 +22,11 @@ If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id: SQLiteChannel+Model.m,v 1.1 2004/06/14 14:27:44 helge Exp $ #include "SQLiteChannel.h" #include "NSString+SQLite.h" #include "EOAttribute+SQLite.h" -#import "common.h" +#include "common.h" @interface EORelationship(FixMe) - (void)addJoin:(id)_join; @@ -41,17 +40,19 @@ NSArray *resultDescription; NSDictionary *row; - if (![_tableName length]) + if ([_tableName length] == 0) return nil; - if (!(attributes = [self->_attributesForTableName - objectForKey:_tableName])) { - sqlExpr = - @"SELECT a.attnum, a.attname, t.typname, a.attlen, a.attnotnull " - @"FROM pg_class c, pg_attribute a, pg_type t " - @"WHERE c.relname='%@' AND a.attnum>0 AND a.attrelid=c.oid AND a.atttypid=t.oid " - @"ORDER BY attnum;"; + attributes = [self->_attributesForTableName objectForKey:_tableName]; + if (attributes == nil) { +#if 1 + // TODO: we would need to parse the SQL field of 'sqlite_master'? + NSLog(@"ERROR(%s): operation not supported on SQLite!", + __PRETTY_FUNCTION__); + return nil; +#else sqlExpr = [NSString stringWithFormat:sqlExpr, _tableName]; +#endif if (![self evaluateExpression:sqlExpr]) { fprintf(stderr, @@ -70,7 +71,7 @@ NSString *attrName = nil; columnName = [[row objectForKey:@"attname"] stringValue]; - attrName = [columnName _pgModelMakeInstanceVarName]; + attrName = [columnName _sqlite3ModelMakeInstanceVarName]; externalType = [[row objectForKey:@"typname"] stringValue]; attribute = [[EOAttribute alloc] init]; @@ -79,7 +80,7 @@ [attribute setExternalType:externalType]; [attribute loadValueClassForExternalSQLiteType:externalType]; [attributes addObject:attribute]; - RELEASE(attribute); + [attribute release]; } [self->_attributesForTableName setObject:attributes forKey:_tableName]; //NSLog(@"got attrs: %@", attributes); @@ -88,12 +89,12 @@ } - (NSArray *)_primaryKeysNamesForTableName:(NSString *)_tableName { - NSArray *pkNameForTableName = nil; + //NSArray *pkNameForTableName = nil; if ([_tableName length] == 0) return nil; - NSLog(@"%s: not supported on SQLite!", __PRETTY_FUNCTION__); + NSLog(@"ERROR(%s): operation not supported on SQLite!", __PRETTY_FUNCTION__); return nil; } @@ -108,23 +109,23 @@ for (cnt = 0; cnt < tc; cnt++) { NSMutableDictionary *relNamesUsed = - AUTORELEASE([NSMutableDictionary new]); + [NSMutableDictionary dictionaryWithCapacity:16]; NSMutableArray *classProperties = - AUTORELEASE([NSMutableArray new]); + [NSMutableArray arrayWithCapacity:16]; NSMutableArray *primaryKeyAttributes = - AUTORELEASE([NSMutableArray new]); + [NSMutableArray arrayWithCapacity:2]; NSString *tableName = [_tableNames objectAtIndex:cnt]; NSArray *attributes = [self _attributesForTableName:tableName]; NSArray *pkeys = [self _primaryKeysNamesForTableName:tableName]; NSArray *fkeys = [self _foreignKeysForTableName:tableName]; - EOEntity *entity = AUTORELEASE([EOEntity new]); + EOEntity *entity = [[EOEntity new] autorelease]; int cnt2; int ac = [attributes count]; int fkc = [fkeys count]; - [entity setName:[tableName _pgModelMakeClassName]]; + [entity setName:[tableName _sqlite3ModelMakeClassName]]; [entity setClassName: - [@"EO" stringByAppendingString:[tableName _pgModelMakeClassName]]]; + [@"EO" stringByAppendingString:[tableName _sqlite3ModelMakeClassName]]]; [entity setExternalName:tableName]; [classProperties addObjectsFromArray:[entity classProperties]]; [primaryKeyAttributes addObjectsFromArray:[entity primaryKeyAttributes]]; @@ -151,17 +152,19 @@ NSString *da = [fkey objectForKey:@"targetAttr"]; NSString *dt = [fkey objectForKey:@"targetTable"]; EORelationship *rel = - AUTORELEASE([[EORelationship alloc] init]); + [[[EORelationship alloc] init] autorelease]; EOJoin *join = - AUTORELEASE([[EOJoin alloc] init]); + [[[EOJoin alloc] init] autorelease]; NSString *relName = nil; - if ([pkeys containsObject:sa]) - relName = [@"to" stringByAppendingString:[dt _pgModelMakeClassName]]; + if ([pkeys containsObject:sa]) { + relName = [@"to" stringByAppendingString: + [dt _sqlite3ModelMakeClassName]]; + } else { relName = [@"to" stringByAppendingString: - [[sa _pgModelMakeInstanceVarName] - _pgStringWithCapitalizedFirstChar]]; + [[sa _sqlite3ModelMakeInstanceVarName] + _sqlite3StringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; @@ -171,7 +174,8 @@ if ([relNamesUsed objectForKey:relName]) { int useCount = [[relNamesUsed objectForKey:relName] intValue]; - [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)] forKey:relName]; + [relNamesUsed setObject:[NSNumber numberWithInt:(useCount++)] + forKey:relName]; relName = [NSString stringWithFormat:@"%s%d", [relName cString], useCount]; } @@ -179,14 +183,14 @@ [relNamesUsed setObject:[NSNumber numberWithInt:0] forKey:relName]; [rel setName:relName]; - //[rel setDestinationEntity:(EOEntity *)[dt _pgModelMakeClassName]]; + //[rel setDestinationEntity:(EOEntity *)[dt _sqlite3ModelMakeClassName]]; [rel setToMany:NO]; // TODO: EOJoin is removed, fix this ... [(id)join setSourceAttribute: - (EOAttribute *)[sa _pgModelMakeInstanceVarName]]; + (EOAttribute *)[sa _sqlite3ModelMakeInstanceVarName]]; [(id)join setDestinationAttribute: - (EOAttribute *)[da _pgModelMakeInstanceVarName]]; + (EOAttribute *)[da _sqlite3ModelMakeInstanceVarName]]; [rel addJoin:join]; [entity addRelationship:rel]; @@ -222,8 +226,8 @@ [(EOEntity *)[reverse destinationEntity] name]]; else { relName = [@"to" stringByAppendingString: - [[[sa name] _pgModelMakeInstanceVarName] - _pgStringWithCapitalizedFirstChar]]; + [[[sa name] _sqlite3ModelMakeInstanceVarName] + _sqlite3StringWithCapitalizedFirstChar]]; if ([relName hasSuffix:@"Id"]) { int cLength = [relName cStringLength]; @@ -269,23 +273,18 @@ NSDictionary *row = nil; NSString *selectExpression = nil; - selectExpression = - @"SELECT relname " - @"FROM pg_class " - @"WHERE (relkind='r') AND relname !~ '^pg_' AND relname !~ '^xinv[0-9]+' " - @"ORDER BY relname"; - + selectExpression = @"SELECT name FROM sqlite_master WHERE type='table'"; if (![self evaluateExpression:selectExpression]) { - fprintf(stderr, "Couldn`t evaluate table-describe expression '%s'\n", + fprintf(stderr, "Could not evaluate table-describe expression '%s'\n", [selectExpression cString]); return nil; } resultDescription = [self describeResults]; - attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name]; - tableNames = [NSMutableArray arrayWithCapacity:16]; - - while ((row = [self fetchAttributes:resultDescription withZone:NULL])) + attributeName = [(EOAttribute *)[resultDescription objectAtIndex:0] name]; + tableNames = [NSMutableArray arrayWithCapacity:16]; + + while ((row = [self fetchAttributes:resultDescription withZone:NULL])!=nil) [tableNames addObject:[row objectForKey:attributeName]]; return tableNames; diff --git a/sope-gdl1/SQLite3/SQLiteChannel.h b/sope-gdl1/SQLite3/SQLiteChannel.h index c38f9243..29323b22 100644 --- a/sope-gdl1/SQLite3/SQLiteChannel.h +++ b/sope-gdl1/SQLite3/SQLiteChannel.h @@ -37,7 +37,11 @@ void *_connection; // valid during -evaluateExpression: + void *statement; + BOOL hasPendingRow; + void *results; +#if 0 int tupleCount; int fieldCount; BOOL containsBinaryData; @@ -45,6 +49,7 @@ NSString *cmdTuples; NSString *oidStatus; int currentTuple; +#endif // turns on/off channel debugging BOOL isDebuggingEnabled; diff --git a/sope-gdl1/SQLite3/SQLiteChannel.m b/sope-gdl1/SQLite3/SQLiteChannel.m index 47649fa0..8db9b5b9 100644 --- a/sope-gdl1/SQLite3/SQLiteChannel.m +++ b/sope-gdl1/SQLite3/SQLiteChannel.m @@ -52,8 +52,9 @@ static EONull *null = nil; if ((self = [super initWithAdaptorContext:_adaptorContext])) { [self setDebugEnabled:[[NSUserDefaults standardUserDefaults] boolForKey:@"SQLiteDebugEnabled"]]; - self->_attributesForTableName = [[NSMutableDictionary alloc] - initWithCapacity:16]; + + self->_attributesForTableName = + [[NSMutableDictionary alloc] initWithCapacity:16]; self->_primaryKeysNamesForTableName = [[NSMutableDictionary alloc] initWithCapacity:16]; } @@ -99,23 +100,23 @@ static int openConnectionCount = 0; } - (int)maxOpenConnectionCount { - static int MaxOpenConnectionCount = -1; + static int MaxOpenConnectionCount = -1; - if (MaxOpenConnectionCount == -1) { - MaxOpenConnectionCount = - [[NSUserDefaults standardUserDefaults] - integerForKey:@"SQLiteMaxOpenConnectionCount"]; - if (MaxOpenConnectionCount == 0) { - MaxOpenConnectionCount = 15; - } - } + if (MaxOpenConnectionCount != -1) return MaxOpenConnectionCount; + + MaxOpenConnectionCount = + [[NSUserDefaults standardUserDefaults] + integerForKey:@"SQLiteMaxOpenConnectionCount"]; + if (MaxOpenConnectionCount == 0) + MaxOpenConnectionCount = 15; + return MaxOpenConnectionCount; } - (BOOL)openChannel { SQLiteAdaptor *adaptor; int rc; - + if (self->_connection) { NSLog(@"%s: Connection already open !!!", __PRETTY_FUNCTION__); return NO; @@ -126,17 +127,11 @@ static int openConnectionCount = 0; if (![super openChannel]) return NO; -#if 0 - NSLog(@"+++++++++ %s: openConnectionCount %d", __PRETTY_FUNCTION__, - openConnectionCount); -#endif - { - if (openConnectionCount > [self maxOpenConnectionCount]) { - [SQLiteCouldNotOpenChannelException + if (openConnectionCount > [self maxOpenConnectionCount]) { + [SQLiteCouldNotOpenChannelException raise:@"NoMoreConnections" format:@"cannot open a additional connection !"]; - return NO; - } + return NO; } rc = sqlite3_open([[adaptor databaseName] UTF8String], @@ -173,19 +168,11 @@ static int openConnectionCount = 0; } - (void)primaryCloseChannel { - self->tupleCount = 0; - self->fieldCount = 0; - self->containsBinaryData = NO; - - if (self->results) { - free(self->results); - self->results = NO; + if (self->statement != NULL) { + sqlite3_finalize(self->statement); + self->statement = NULL; } - - RELEASE(self->cmdStatus); self->cmdStatus = nil; - RELEASE(self->cmdTuples); self->cmdTuples = nil; - RELEASE(self->oidStatus); self->oidStatus = nil; - + if (self->_connection != NULL) { sqlite3_close(self->_connection); #if 0 @@ -210,37 +197,45 @@ static int openConnectionCount = 0; /* fetching rows */ -- (void)cancelFetch { - if (![self isOpen]) { - [SQLiteException raise:@"ChannelNotOpenException" - format:@"No fetch in progress, connection is not open" - @" (channel=%@)", self]; - } - -#if 0 - NSLog(@"canceling fetch (%i tuples remaining).", - (self->tupleCount - self->currentTuple)); -#endif +- (NSException *)_makeSQLiteStep { + NSString *r; + int rc; - self->tupleCount = 0; - self->currentTuple = 0; - self->fieldCount = 0; - self->containsBinaryData = NO; - - if (self->results) { - free(self->results); - self->results = NO; + rc = sqlite3_step(self->statement); + + if (rc == SQLITE_ROW) { + self->hasPendingRow = YES; + return nil /* no error */; + } + if (rc == SQLITE_DONE) { + self->hasPendingRow = NO; + return nil /* no error */; } - RELEASE(self->cmdStatus); self->cmdStatus = nil; - RELEASE(self->cmdTuples); self->cmdTuples = nil; - RELEASE(self->oidStatus); self->oidStatus = nil; + if (rc == SQLITE_ERROR) + r = [NSString stringWithUTF8String:sqlite3_errmsg(self->_connection)]; + else if (rc == SQLITE_MISUSE) + r = @"Somehow the SQLite method was called in an incorrect way."; + else if (rc == SQLITE_BUSY) + r = @"The SQLite is busy."; + else + r = [NSString stringWithFormat:@"Unexpected SQLite error: %i", rc]; + + return [SQLiteException exceptionWithName:@"FetchFailed" + reason:r userInfo:nil]; +} +- (void)cancelFetch { + if (self->statement != NULL) { + sqlite3_finalize(self->statement); + self->statement = NULL; + } [super cancelFetch]; } - (NSArray *)describeResults { - int cnt; + // TODO: make exception-less method + int cnt, fieldCount; NSMutableArray *result = nil; NSMutableDictionary *usedNames = nil; NSNumber *yesObj; @@ -251,21 +246,40 @@ static int openConnectionCount = 0; [SQLiteException raise:@"NoFetchInProgress" format:@"No fetch in progress (channel=%@)", self]; } + + /* we need to fetch a row to get the info */ + + if (!self->hasPendingRow) { + NSException *error; + + if ((error = [self _makeSQLiteStep]) != nil) { + [self cancelFetch]; + [error raise]; // raise error, TODO: make exception-less method + return nil; + } + } + if (!self->hasPendingRow) /* no rows available */ + return nil; + + fieldCount = sqlite3_column_count(self->statement); + +#warning TODO: describe row + // allowsNull, columnName, externType, name, valueClassName, valueType + NSLog(@"%s: TODO describe current row ...", __PRETTY_FUNCTION__); + + /* old code below */ - result = [[NSMutableArray alloc] initWithCapacity:self->fieldCount]; - usedNames = [[NSMutableDictionary alloc] initWithCapacity:self->fieldCount]; + result = [[NSMutableArray alloc] initWithCapacity:fieldCount]; + usedNames = [[NSMutableDictionary alloc] initWithCapacity:fieldCount]; - for (cnt = 0; cnt < self->fieldCount; cnt++) { + for (cnt = 0; cnt < fieldCount; cnt++) { EOAttribute *attribute = nil; NSString *columnName = nil; NSString *attrName = nil; - -#if 1 -# warning TODO, columnName -#else - columnName = [NSString stringWithCString:self->fieldInfo[cnt].name]; -#endif - attrName = [columnName _pgModelMakeInstanceVarName]; + + columnName = [NSString stringWithCString: + sqlite3_column_name(self->statement, cnt)]; + attrName = [columnName _sqlite3ModelMakeInstanceVarName]; if ([[usedNames objectForKey:attrName] boolValue]) { int cnt2 = 0; @@ -273,11 +287,13 @@ static int openConnectionCount = 0; NSString *newAttrName = nil; for (cnt2 = 2; cnt2 < 100; cnt2++) { + NSString *s; sprintf(buf, "%i", cnt2); - + // TODO: unicode - newAttrName = [attrName stringByAppendingString: - [NSString stringWithCString:buf]]; + s = [[NSString alloc] initWithCString:buf]; + newAttrName = [attrName stringByAppendingString:s]; + [s release]; if (![[usedNames objectForKey:newAttrName] boolValue]) { attrName = newAttrName; @@ -314,72 +330,72 @@ static int openConnectionCount = 0; return [result autorelease]; } +- (BOOL)isColumnNullInCurrentRow:(int)_column { + /* + Note: NULL is SQLite is represented as empty strings ..., don't know + what to do about that? + At least Sybase 10 doesn't support empty strings strings as well + and converts them to a single space. So maybe it is reasonable to + map empty strings to NSNull? + + Or is this column-type SQLITE_NULL? If so, thats rather weird, + since the type query does not take a row. + */ + return NO; +} + - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes withZone:(NSZone *)_zone { + /* + Note: we expect that the attributes match the generated SQL. This is + because auto-generated SQL can contain SQL table prefixes (like + alias.column-name which cannot be detected using the attributes + schema) + */ + // TODO: add a primaryFetchAttributesX method? NSMutableDictionary *row = nil; + NSException *error; unsigned attrCount = [_attributes count]; - int indices[attrCount]; unsigned cnt; - if (self->currentTuple == self->tupleCount) { - if (self->results) [self cancelFetch]; + if (self->statement == NULL) { + NSLog(@"ERROR: no fetch in progress?"); + [self cancelFetch]; return nil; } - { -#if 1 -# warning TODO: field name processing - NSMutableArray *fieldNames; - //unsigned nFields, i; - - // TODO: we could probably cache the field-name array for much more speed ! - fieldNames = [[NSMutableArray alloc] initWithCapacity:32]; -#else - nFields = PQnfields(self->results); - for (i = 0; i < nFields; i++) { - NSString *s; - - s = [[NSString alloc] initWithCString:PQfname(self->results, i)]; - [fieldNames addObject:s]; - [s release]; - } -#endif - - for (cnt = 0; cnt < attrCount; cnt++) { - EOAttribute *attribute = [_attributes objectAtIndex:cnt]; - - indices[cnt] = [fieldNames indexOfObject:[attribute columnName]]; - - if (indices[cnt] == NSNotFound) { - [SQLiteException raiseWithFormat: - @"attribute %@ not covered by query", attribute]; - } - [fieldNames replaceObjectAtIndex:indices[cnt] withObject:[EONull null]]; + + if (!self->hasPendingRow) { + if ((error = [self _makeSQLiteStep]) != nil) { + [self cancelFetch]; + [error raise]; // raise error, TODO: make exception-less method + return nil; } - [fieldNames release]; fieldNames = nil; + } + if (!self->hasPendingRow) { /* step was fine, but we are at the end */ + [self cancelFetch]; + return nil; } - + self->hasPendingRow = NO; /* consume the row */ + + /* build row */ + row = [NSMutableDictionary dictionaryWithCapacity:attrCount]; for (cnt = 0; cnt < attrCount; cnt++) { EOAttribute *attribute; NSString *attrName; id value = nil; - + attribute = [_attributes objectAtIndex:cnt]; attrName = [attribute name]; -#if 1 -# warning TODO: value creation -#else - if (PQgetisnull(self->results, self->currentTuple, indices[cnt])) { - value = null; + if ([self isColumnNullInCurrentRow:cnt]) { + value = [null retain]; } else { - Class valueClass = Nil; - const char *pvalue; - int vallen; + Class valueClass; valueClass = NSClassFromString([attribute valueClassName]); if (valueClass == Nil) { @@ -391,25 +407,36 @@ static int openConnectionCount = 0; continue; } - pvalue = PQgetvalue(self->results, self->currentTuple, indices[cnt]); - vallen = PQgetlength(self->results, self->currentTuple, indices[cnt]); - - if (self->containsBinaryData) { - // pvalue is stored in internal representation - - value = [valueClass valueFromBytes:pvalue length:vallen - sqlite3Type:[attribute externalType] - attribute:attribute - adaptorChannel:self]; - } - else { - // pvalue is ASCII string - - value = [valueClass valueFromCString:pvalue length:vallen - sqlite3Type:[attribute externalType] - attribute:attribute - adaptorChannel:self]; + switch (sqlite3_column_type(self->statement, cnt)) { + case SQLITE_INTEGER: + value = [[valueClass alloc] + initWithSQLiteInt:sqlite3_column_int(self->statement, cnt)]; + break; + case SQLITE_FLOAT: + value = [[valueClass alloc] + initWithSQLiteDouble: + sqlite3_column_double(self->statement, cnt)]; + break; + case SQLITE_TEXT: + value = [[valueClass alloc] + initWithSQLiteText: + sqlite3_column_text(self->statement, cnt)]; + break; + case SQLITE_BLOB: + value = [[valueClass alloc] + initWithSQLiteData: + sqlite3_column_blob(self->statement, cnt) + length:sqlite3_column_bytes(self->statement, cnt)]; + break; + case SQLITE_NULL: + value = [null retain]; + break; + default: + NSLog(@"ERROR(%s): unexpected SQLite type at column %i", + __PRETTY_FUNCTION__, cnt); + continue; } + if (value == nil) { NSLog(@"ERROR(%s): %@: got no value for column:\n" @" attribute=%@\n valueClass=%@\n type=%@", @@ -419,107 +446,139 @@ static int openConnectionCount = 0; continue; } } -#endif - - [row setObject:value forKey:attrName]; + + if (value != nil) { + [row setObject:value forKey:attrName]; + [value release]; + } } - - self->currentTuple++; - + return row; } /* sending SQL to server */ -static int sqlite_result_callback -(void *userdata, int columnCount, char **columns, char **columnNames) -{ - /* need to load into array ... */ - SQLiteChannel *self = userdata; - - NSLog(@"%@: SQLite callback, %i columns ...", self, columnCount); - return 0; -} - -- (BOOL)evaluateExpression:(NSString *)_expression { - char *zErrMsg = NULL; - BOOL result; +- (NSException *)evaluateExpressionX:(NSString *)_expression { + NSMutableString *sql; + NSException *error; + char *zErrMsg = NULL; + BOOL result; + const char *s; + const char *tails = NULL; int rc; *(&result) = YES; - + if (_expression == nil) { [NSException raise:@"InvalidArgumentException" format:@"parameter for evaluateExpression: " @"must not be null (channel=%@)", self]; } - *(&_expression) = [[_expression mutableCopy] autorelease]; + sql = [[_expression mutableCopy] autorelease]; + /* ask delegate */ + if (delegateRespondsTo.willEvaluateExpression) { EODelegateResponse response; - - response = - [delegate adaptorChannel:self - willEvaluateExpression:(NSMutableString *)_expression]; - if (response == EODelegateRejects) - return NO; + response = [delegate adaptorChannel:self willEvaluateExpression:sql]; + + if (response == EODelegateRejects) { + return [NSException exceptionWithName:@"EODelegateRejects" + reason:@"delegate rejected insert" + userInfo:nil]; + } if (response == EODelegateOverrides) - return YES; + return nil; } + + /* check some preconditions */ if (![self isOpen]) { - [SQLiteException raise:@"ChannelNotOpenException" - format:@"SQLite connection is not open (channel=%@)", - self]; - return NO; + return [SQLiteException exceptionWithName:@"ChannelNotOpenException" + reason:@"SQLite connection is not open" + userInfo:nil]; } - if (self->results != NULL) { - [SQLiteException raise:@"CommandInProgressException" - format:@"an evaluation is in progress (channel=%@)",self]; + if (self->statement != NULL) { + return [SQLiteException exceptionWithName:@"CommandInProgressException" + reason:@"an evaluation is in progress" + userInfo:nil]; return NO; } - + + if ([self isFetchInProgress]) { + NSLog(@"WARNING: a fetch is still in progress: %@", self); + [self cancelFetch]; + } + if (isDebuggingEnabled) - NSLog(@"%@ sql: %@", self, _expression); + NSLog(@"%@ SQL: %@", self, sql); + /* reset environment */ + self->isFetchInProgress = NO; - self->tupleCount = 0; - self->fieldCount = 0; - self->currentTuple = 0; - self->containsBinaryData = NO; - - rc = sqlite3_exec(self->_connection, - [_expression UTF8String], - sqlite_result_callback, - self /* userdata */, - &zErrMsg); + + s = [sql UTF8String]; + rc = sqlite3_prepare(self->_connection, s, strlen(s), + (void *)&(self->statement), &tails); + if (rc != SQLITE_OK) { - NSString *err; - - if (zErrMsg) { - err = [NSString stringWithCString:zErrMsg]; - free(zErrMsg); + [self cancelFetch]; + // TODO: improve error + return [SQLiteException exceptionWithName:@"ExecutionFailed" + reason:@"could not parse SQL statement" + userInfo:nil]; + } + + /* step to first row */ + + if ([sql hasPrefix:@"SELECT"] || [sql hasPrefix:@"select"]) { + self->isFetchInProgress = YES; + NSAssert(self->statement, @"missing statement"); + } + else { + if ((error = [self _makeSQLiteStep]) != nil) { + [self cancelFetch]; + return error; + } + + self->isFetchInProgress = self->hasPendingRow; + if (!self->isFetchInProgress) { + sqlite3_finalize(self->statement); + self->statement = NULL; } - else - err = nil; - - [SQLiteException raise:@"ExecutionFailed" - format: - @"the sqlite_exec(%@) call failed (channel=%@): %s", - _expression, self, err]; - return NO; } - if (zErrMsg) { - NSLog(@"WARNING(%@): pending error message: '%s'", self, zErrMsg); + + /* check whether there are pending errors */ + + if (zErrMsg != NULL) { + NSLog(@"WARNING(%s): %@ pending error message: '%s'", + __PRETTY_FUNCTION__, self, zErrMsg); free(zErrMsg); } - + /* only on empty results? */ if (delegateRespondsTo.didEvaluateExpression) - [delegate adaptorChannel:self didEvaluateExpression:_expression]; + [delegate adaptorChannel:self didEvaluateExpression:sql]; + return nil /* everything is OK */; +} +- (BOOL)evaluateExpression:(NSString *)_sql { + NSException *e; + NSString *n; + + if ((e = [self evaluateExpressionX:_sql]) == nil) + return YES; + + /* for compatibility with non-X methods, translate some errors to a bool */ + n = [e name]; + if ([n isEqualToString:@"EOEvaluationError"]) + return NO; + if ([n isEqualToString:@"EODelegateRejects"]) + return NO; + + [e raise]; return NO; } @@ -553,39 +612,23 @@ static int sqlite_result_callback pkey = nil; seq = nil; - if ([seqName length] > 0) - seq = [NSString stringWithFormat:@"SELECT NEXTVAL ('%@')", seqName]; - else - seq = [adaptor newKeyExpression]; + seq = ([seqName length] > 0) + ? [NSString stringWithFormat:@"SELECT NEXTVAL ('%@')", seqName] + : [adaptor newKeyExpression]; NS_DURING { if ([self evaluateExpression:seq]) { id key = nil; -#if 0 - if (self->tupleCount > 0) { - if (PQgetisnull(self->results, 0, 0)) - key = null; - else { - const char *pvalue; - int vallen; - - if (self->containsBinaryData) { - [self notImplemented:_cmd]; - } - - pvalue = PQgetvalue(self->results, 0, 0); - vallen = PQgetlength(self->results, 0, 0); - - if (pvalue) - key = [NSNumber numberWithInt:atoi(pvalue)]; - } + + NSLog(@"ERROR: new key creation is not implemented in SQLite yet!"); + if ([self isFetchInProgress]) { + NSLog(@"Primary key eval returned results .."); } -#endif // TODO NSLog(@"%s: PKEY GEN NOT IMPLEMENTED!", __PRETTY_FUNCTION__); [self cancelFetch]; - if (key) { + if (key != nil) { pkey = [NSDictionary dictionaryWithObject:key forKey:[pkeys objectAtIndex:0]]; } diff --git a/sope-gdl1/SQLite3/SQLiteContext.m b/sope-gdl1/SQLite3/SQLiteContext.m index 18bdaf6c..31604f3d 100644 --- a/sope-gdl1/SQLite3/SQLiteContext.m +++ b/sope-gdl1/SQLite3/SQLiteContext.m @@ -39,11 +39,11 @@ - (BOOL)primaryBeginTransaction { BOOL result; - + result = [[[channels lastObject] nonretainedObjectValue] evaluateExpression:@"BEGIN TRANSACTION"]; - + return result; } diff --git a/sope-gdl1/SQLite3/SQLiteValues.h b/sope-gdl1/SQLite3/SQLiteValues.h index 0f40a88c..1372816b 100644 --- a/sope-gdl1/SQLite3/SQLiteValues.h +++ b/sope-gdl1/SQLite3/SQLiteValues.h @@ -47,21 +47,20 @@ @protocol SQLiteValues -+ (id)valueFromCString:(const char *)_cstr length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel; - -+ (id)valueFromBytes:(const void *)_bytes length:(int)_length - sqlite3Type:(NSString *)_type - attribute:(EOAttribute *)_attribute - adaptorChannel:(SQLiteChannel *)_channel; - - (NSString *)stringValueForSQLite3Type:(NSString *)_type attribute:(EOAttribute *)_attribute; @end +@interface NSObject(SQLiteValues) + +- (id)initWithSQLiteInt:(int)_value; +- (id)initWithSQLiteText:(const unsigned char *)_value; +- (id)initWithSQLiteDouble:(double)_value; +- (id)initWithSQLiteData:(const void *)_data length:(int)_length; + +@end + @interface NSString(SQLiteValues) < SQLiteValues > @end diff --git a/sope-gdl1/SQLite3/SQLiteValues.m b/sope-gdl1/SQLite3/SQLiteValues.m index 19ac4f11..fdbe6c05 100644 --- a/sope-gdl1/SQLite3/SQLiteValues.m +++ b/sope-gdl1/SQLite3/SQLiteValues.m @@ -73,6 +73,70 @@ @end /* NSNull(SQLiteValues) */ +@implementation NSObject(SQLiteValues) + +- (id)initWithSQLiteInt:(int)_value { + if ([self respondsToSelector:@selector(initWithInt:)]) + return [(NSNumber *)self initWithInt:_value]; + + if ([self respondsToSelector:@selector(initWithDouble:)]) + return [(NSNumber *)self initWithDouble:_value]; + + if ([self respondsToSelector:@selector(initWithString:)]) { + NSString *s; + char buf[256]; + + sprintf(buf, "%i", _value); + s = [[NSString alloc] initWithCString:buf]; + self = [(NSString *)self initWithString:s]; + [s release]; + return self; + } + + [self release]; + return nil; +} + +- (id)initWithSQLiteDouble:(double)_value { + if ([self respondsToSelector:@selector(initWithDouble:)]) + return [(NSNumber *)self initWithDouble:_value]; + + [self release]; + return nil; +} + +- (id)initWithSQLiteText:(const unsigned char *)_value { + if ([self respondsToSelector:@selector(initWithString:)]) { + NSString *s; + + s = [[NSString alloc] initWithUTF8String:_value]; + self = [(NSString *)self initWithString:s]; + [s release]; + return self; + } + + [self release]; + return nil; +} + +- (id)initWithSQLiteData:(const void *)_data length:(int)_length { + if ([self respondsToSelector:@selector(initWithBytes:length:)]) + return [(NSData *)self initWithBytes:_data length:_length]; + + if ([self respondsToSelector:@selector(initWithData:)]) { + NSData *d; + + d = [[NSData alloc] initWithBytes:_data length:_length]; + self = [(NSData *)self initWithData:d]; + [d release]; + return self; + } + + [self release]; + return nil; +} + +@end /* NSObject(SQLiteValues) */ void __link_SQLiteValues() { // used to force linking of object file diff --git a/sope-gdl1/SQLite3/Version b/sope-gdl1/SQLite3/Version index f5da07a4..b191a15e 100644 --- a/sope-gdl1/SQLite3/Version +++ b/sope-gdl1/SQLite3/Version @@ -1,3 +1,3 @@ -# $Id: Version,v 1.1 2004/06/14 14:27:44 helge Exp $ +# Version file -SUBMINOR_VERSION:=8 +SUBMINOR_VERSION:=9 diff --git a/sope-gdl1/SQLite3/gdltest.m b/sope-gdl1/SQLite3/gdltest.m index cad5fdb8..a8ac58af 100644 --- a/sope-gdl1/SQLite3/gdltest.m +++ b/sope-gdl1/SQLite3/gdltest.m @@ -27,7 +27,72 @@ #import #include +static void fetchExprInChannel(NSString *expr, EOAdaptorChannel *ch) { + NSArray *attrs; + NSDictionary *record; + + if (![expr isNotNull]) return; + + if (![ch evaluateExpression:expr]) { + NSLog(@"ERROR: failed to evaluate: %@", expr); + return; + } + + attrs = [ch describeResults]; + NSLog(@"results: %@", attrs); + + while ((record = [ch fetchAttributes:attrs withZone:nil]) != nil) + NSLog(@"fetched %@", record); +} + +static void fetchSomePersonRecord(EOEntity *e, EOAdaptorChannel *ch) { + EOSQLQualifier *q; + NSArray *attrs; + + attrs = [e attributes]; + q = [[EOSQLQualifier alloc] + initWithEntity:e + qualifierFormat:@"%A='helge'", @"login"]; + [q autorelease]; + + if ([ch selectAttributes:attrs + describedByQualifier:q + fetchOrder:nil + lock:NO]) { + NSDictionary *record; + + record = [ch fetchAttributes:attrs withZone:nil]; + } + else + NSLog(@"Could not select .."); +} + +static void fetchSomeTeamRecords(EOEntity *e, EOAdaptorChannel *ch) { + EOSQLQualifier *q; + NSArray *attrs; + + q = [e qualifier]; + attrs = [e attributes]; + + if ([ch selectAttributes:attrs describedByQualifier:q fetchOrder:nil + lock:NO]) { + NSDictionary *record; + + while ((record = [ch fetchAttributes:attrs withZone:NULL]) != nil) { + NSLog(@"fetched %@ birthday %@", + [record valueForKey:@"description"], + [record valueForKey:@"companyId"]); + } + } + else + NSLog(@"Could not select team records .."); +} + static void runtestInOpenChannel(EOAdaptorChannel *ch) { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + EOEntity *e; + EOSQLQualifier *q; + NSArray *attrs; EOAdaptorContext *ctx; EOModel *m; NSString *expr; @@ -38,109 +103,61 @@ static void runtestInOpenChannel(EOAdaptorChannel *ch) { expr = [[NSUserDefaults standardUserDefaults] stringForKey:@"sql"]; NSLog(@"channel is open"); - - if ([ctx beginTransaction]) { - NSLog(@"began tx .."); + + if (![ctx beginTransaction]) { + NSLog(@"ERROR: could not begin transaction ..."); + return; + } - /* do something */ - { - NSAutoreleasePool *pool = [NSAutoreleasePool new]; - EOEntity *e; - EOSQLQualifier *q; - NSArray *attrs; + NSLog(@"began tx .."); + /* do something */ + pool = [[NSAutoreleasePool alloc] init]; #if 1 - /* fetch some expr */ - - if (expr) { - if ([ch evaluateExpression:expr]) { - NSDictionary *record; - - attrs = [ch describeResults]; - NSLog(@"results: %@", attrs); - - while ((record = [ch fetchAttributes:attrs withZone:nil])) - NSLog(@"fetched %@", record); - } - } + fetchExprInChannel(expr, ch); #endif - /* fetch some doof records */ - - e = [m entityNamed:@"MyEntity"]; - NSLog(@"entity: %@", e); - if (e == nil) - exit(1); - - q = [e qualifier]; - attrs = [e attributes]; - - if ([ch selectAttributes:attrs - describedByQualifier:q - fetchOrder:nil - lock:NO]) { - NSDictionary *record; - - while ((record = [ch fetchAttributes:attrs withZone:nil])) { - NSLog(@"fetched %@ birthday %@", - [record valueForKey:@"pkey"], - [record valueForKey:@"companyId"]); - } - } - else - NSLog(@"Could not select .."); - - /* fetch some team records */ - - if ((e = [m entityNamed:@"Team"])) { - q = [e qualifier]; - attrs = [e attributes]; - - if ([ch selectAttributes:attrs - describedByQualifier:q - fetchOrder:nil - lock:NO]) { - NSDictionary *record; - - while ((record = [ch fetchAttributes:attrs withZone:nil])) { - NSLog(@"fetched %@ birthday %@", - [record valueForKey:@"description"], - [record valueForKey:@"companyId"]); - } - } - else - NSLog(@"Could not select .."); - } + + /* fetch some MyEntity records */ + + e = [m entityNamed:@"MyEntity"]; + NSLog(@"entity: %@", e); + if (e == nil) + exit(1); - /* do some update */ - - if ((e = [m entityNamed:@"Person"])) { - attrs = [e attributes]; - q = [[EOSQLQualifier alloc] - initWithEntity:e - qualifierFormat:@"%A='helge'", @"login"]; - AUTORELEASE(q); - - if ([ch selectAttributes:attrs - describedByQualifier:q - fetchOrder:nil - lock:NO]) { - NSDictionary *record; - - record = [ch fetchAttributes:attrs withZone:nil]; - } - else - NSLog(@"Could not select .."); - } - - RELEASE(pool); - } + q = [e qualifier]; + attrs = [e attributes]; + + // NSLog(@"ATTRS: %@", attrs); + + if ([ch selectAttributes:attrs + describedByQualifier:q + fetchOrder:nil + lock:NO]) { + NSDictionary *record; + + while ((record = [ch fetchAttributes:attrs withZone:nil]) != nil) + NSLog(@"fetched record: %@", record); + } + else + NSLog(@"Could not select .."); + + /* some OGo fetches */ + + if ((e = [m entityNamed:@"Team"]) != nil) + fetchSomeTeamRecords(e, ch); + + if ((e = [m entityNamed:@"Person"]) != nil) + fetchSomePersonRecord(e, ch); + + /* tear down */ + + [pool release]; - NSLog(@"committing tx .."); - if ([ctx commitTransaction]) - NSLog(@" could commit."); - else - NSLog(@" commit failed."); - } + NSLog(@"committing tx .."); + if ([ctx commitTransaction]) + NSLog(@" could commit."); + else + NSLog(@" commit failed."); } static void runtest(void) { -- 2.39.5