From 92e4d1cdfb46a53c25a48618d833e3803ea85c42 Mon Sep 17 00:00:00 2001 From: helge Date: Thu, 13 Jan 2005 23:18:18 +0000 Subject: [PATCH] fixed a bug in the sort order generator, major reorgs git-svn-id: http://svn.opengroupware.org/SOPE/trunk@517 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-gdl1/GDLAccess/ChangeLog | 9 + sope-gdl1/GDLAccess/EOAdaptorDataSource.m | 313 +++++++++++++--------- sope-gdl1/GDLAccess/Version | 2 +- 3 files changed, 189 insertions(+), 135 deletions(-) diff --git a/sope-gdl1/GDLAccess/ChangeLog b/sope-gdl1/GDLAccess/ChangeLog index 8c7bd601..7bee603f 100644 --- a/sope-gdl1/GDLAccess/ChangeLog +++ b/sope-gdl1/GDLAccess/ChangeLog @@ -1,3 +1,12 @@ +2005-01-14 Helge Hess + + * EOAdaptorDataSource.m: fixed a bug in the sorting code, the "AS" was + missing in the SQL rename statement (v4.5.46) + +2005-01-13 Helge Hess + + * EOAdaptorDataSource.m: improved -description (v4.5.45) + 2005-01-04 Helge Hess * EOAttribute.m, EOFaultHandler.m, EODatabaseFaultResolver.m: added diff --git a/sope-gdl1/GDLAccess/EOAdaptorDataSource.m b/sope-gdl1/GDLAccess/EOAdaptorDataSource.m index 38ca9090..87482cff 100644 --- a/sope-gdl1/GDLAccess/EOAdaptorDataSource.m +++ b/sope-gdl1/GDLAccess/EOAdaptorDataSource.m @@ -3,8 +3,7 @@ Copyright (C) SKYRIX Software AG and Helge Hess - Author: Helge Hess (helge.hess@opengroupware.org) - Date: 1999-2004 + Date: 1999-2005 This file is part of the GNUstep Database Library. @@ -23,7 +22,6 @@ If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -// $Id: EOAdaptorDataSource.m 1 2004-08-20 10:38:46Z znek $ /* column-names must have small letterso @@ -64,12 +62,19 @@ static EONull *null = nil; @end /* EOQualifier(SqlExpression) */ @interface EOAdaptorDataSource(Private) + - (NSMutableString *)_selectListWithChannel:(EOAdaptorChannel *)_adChan; - (NSString *)_whereExprWithChannel:(EOAdaptorChannel *)_adChan; - (NSString *)_whereClauseForGlobaID:(EOKeyGlobalID *)_gid adaptor:(EOAdaptor *)_adaptor channel:(EOAdaptorChannel *)_adChan; + +- (NSString *)_orderByExprForAttributes:(NSArray *)_attrs + andPatchSelectList:(NSMutableString *)selectList + withChannel:(EOAdaptorChannel *)_adChan; + - (NSDictionary *)_mapAttrsWithValues:(NSDictionary *)_keyValues tableName:(NSString *)_tableName channel:(EOAdaptorChannel *)_adChan; + @end /* EOAdaptorDataSource(Private) */ @interface EOAdaptorDataSource(Internals) @@ -83,6 +88,7 @@ static EONull *null = nil; @implementation EOAdaptorDataSource +static Class NSCalendarDateClass = nil; static NSNotificationCenter *nc = nil; static NSNotificationCenter *getNC(void ) { @@ -95,8 +101,9 @@ static NSNotificationCenter *getNC(void ) { NSAssert2([super version] == 1, @"invalid superclass (%@) version %i !", NSStringFromClass([self superclass]), [super version]); - if (null == nil) - null = [[EONull null] retain]; + + null = [[EONull null] retain]; + NSCalendarDateClass = [NSCalendarDate class]; } + (int)version { return [super version] + 1; /* v2 */ @@ -239,7 +246,7 @@ static NSNotificationCenter *getNC(void ) { /* TODO: split up this HUGE method! */ NSString *entityName = nil; NSString *whereExpr = nil; - NSMutableString *orderByExpr = nil; + NSString *orderByExpr = nil; NSMutableString *selectList = nil; NSMutableString *expression = nil; NSMutableArray *result = nil; @@ -253,6 +260,7 @@ static NSNotificationCenter *getNC(void ) { BOOL localComTrans; if (self->fetchSpecification == nil) { + // TODO: make that a lastException and just return nil [NSException raise:NSInvalidArgumentException format:@"fetchSpecification required for table name"]; return nil; @@ -334,105 +342,12 @@ static NSNotificationCenter *getNC(void ) { RELEASE(qualifierKeys); qualifierKeys = nil; } - whereExpr = [self _whereExprWithChannel:adChan]; - selectList = [self _selectListWithChannel:adChan]; - { /* order by expr */ - NSEnumerator *enumerator = nil; - EOSortOrdering *sortOrdering = nil; - int orderCnt = 0; - - enumerator = [[self->fetchSpecification sortOrderings] objectEnumerator]; - - while ((sortOrdering = [enumerator nextObject])) { - SEL selector = NULL; - NSString *key = nil; - EOAttribute *keyAttr = nil; - int order = 0; /* 0 - not used; 1 - asc; 2 - desc */ - BOOL inSensitive = NO; - NSString *orderTmp = nil; - - if (orderByExpr == nil) { - orderByExpr = [NSMutableString stringWithCapacity:64]; - } - else { - [orderByExpr appendString:@", "]; - } - if ((selector = [sortOrdering selector])) { - if (SEL_EQ(selector, EOCompareAscending)) { - order = 1; - } - else if (SEL_EQ(selector, EOCompareDescending)) { - order = 2; - } - else if (SEL_EQ(selector, EOCompareCaseInsensitiveAscending)) { - order = 1; - inSensitive = YES; - } - else if (SEL_EQ(selector, EOCompareCaseInsensitiveDescending)) { - inSensitive = YES; - order = 2; - } - } - key = [sortOrdering key]; - - if (key == nil || [key length] == 0) { - NSLog(@"WARNING[%s]: wrong key in sortordering %@", - __PRETTY_FUNCTION__, key); - continue; - } - { - NSEnumerator *en = nil; - id obj = nil; - - key = [key lowercaseString]; - en = [attrs objectEnumerator]; - while ((obj = [en nextObject])) { - if ([[[(EOAttribute *)obj columnName] lowercaseString] - isEqualToString:key]) - break; - } - if (obj == nil) { - RELEASE(self->__attributes); self->__attributes = nil; - RELEASE(self->__qualifier); self->__qualifier = nil; - RELEASE(expression); expression = nil; - [self rollbackTransaction]; - [[[InvalidAttributeException alloc] - initWithFormat:@"couldn`t find EOAttribute for SortOrdering" - @" %@ Attributes %@", - sortOrdering, attrs] raise]; - } - keyAttr = obj; - } - key = [adaptor formatAttribute:keyAttr]; - orderTmp = [NSString stringWithFormat:@"order_by_expr_%d", orderCnt++]; - [orderByExpr appendString:orderTmp]; - if (order == 1) { - [orderByExpr appendString:@" ASC"]; - } - else if (order == 2) { - [orderByExpr appendString:@" DESC"]; - } - { /* manipulate select expr */ - if (inSensitive) { - if ([[keyAttr valueClassName] isEqualToString:@"NSString"]) { - key = [NSString stringWithFormat:@"LOWER(%@)", key]; - } - else - NSLog(@"WARNING[%s]: inSensitive expression for no text attribute", - __PRETTY_FUNCTION__); - } - { - NSString *str = nil; - - str = [key stringByAppendingString:@" "]; - str = [str stringByAppendingString:orderTmp]; - str = [str stringByAppendingString:@", "]; - - [selectList insertString:str atIndex:0]; - } - } - } - } + whereExpr = [self _whereExprWithChannel:adChan]; + selectList = [self _selectListWithChannel:adChan]; + orderByExpr = [self _orderByExprForAttributes:attrs + andPatchSelectList:selectList + withChannel:adChan]; + expression = [[NSMutableString alloc] initWithCapacity:256]; [expression appendString:@"SELECT "]; @@ -462,19 +377,20 @@ static NSNotificationCenter *getNC(void ) { } result = [NSMutableArray arrayWithCapacity:64]; { - NSMutableDictionary *row = nil; + NSMutableDictionary *row = nil; unsigned fetchCnt = 0; unsigned fetchLimit = 0; unsigned attrCnt = 0; id *values = NULL; id *keys = NULL; - + + /* Note: those are reused in the inner loop */ attrCnt = [attrs count]; values = calloc(attrCnt + 2, sizeof(id)); keys = calloc(attrCnt + 2, sizeof(id)); fetchLimit = [self->fetchSpecification fetchLimit]; - while ((row = [adChan fetchAttributes:attrs withZone:NULL])) { + while ((row = [adChan fetchAttributes:attrs withZone:NULL]) != nil) { NSEnumerator *enumerator = nil; id attr = nil; int rowCnt = 0; @@ -485,26 +401,18 @@ static NSNotificationCenter *getNC(void ) { pKeyVs = calloc(pKeyCnt, sizeof(id)); enumerator = [attrs objectEnumerator]; - while ((attr = [enumerator nextObject])) { + while ((attr = [enumerator nextObject]) != nil) { id obj; NSString *cn; - obj = [row objectForKey:[(EOAttribute *)attr name]]; - + if (obj == nil) continue; - - if (tz) { - static Class NSCalendarDateClass = nil; - - if (NSCalendarDateClass == nil) - NSCalendarDateClass = [NSCalendarDate class]; - - if ([obj isKindOfClass:NSCalendarDateClass]) { - [obj setTimeZone:tz]; - } - } + + if (tz != nil && [obj isKindOfClass:NSCalendarDateClass]) + [obj setTimeZone:tz]; + cn = [[attr columnName] lowercaseString]; values[rowCnt] = obj; keys[rowCnt] = cn; @@ -546,24 +454,23 @@ static NSNotificationCenter *getNC(void ) { } fetchCnt++; r = [[NSMutableDictionary alloc] - initWithObjects:values forKeys:keys count:rowCnt]; + initWithObjects:values forKeys:keys count:rowCnt]; [result addObject:r]; - RELEASE(r); r = nil; - free(pKeyVs); pKeyVs = NULL; - if (fetchLimit == fetchCnt) { + [r release]; r = nil; + if (pKeyVs) free(pKeyVs); pKeyVs = NULL; + if (fetchLimit == fetchCnt) break; - } } - free(values); values = NULL; - free(keys); keys = NULL; + if (values) free(values); values = NULL; + if (keys) free(keys); keys = NULL; } [adChan cancelFetch]; if (localComTrans) [self commitTransaction]; - RELEASE(expression); expression = nil; - RELEASE(self->__qualifier); self->__qualifier = nil; - RELEASE(self->__attributes); self->__attributes = nil; + [expression release]; expression = nil; + [self->__qualifier release]; self->__qualifier = nil; + [self->__attributes release]; self->__attributes = nil; return result; } @@ -957,12 +864,28 @@ static NSNotificationCenter *getNC(void ) { } - (EOFetchSpecification *)fetchSpecification { + /* + Note: the copy is intended, since the fetchspec is mutable, the consumer + could otherwise modify it "behind the scenes" + */ return [[self->fetchSpecification copy] autorelease]; } +/* description */ + - (NSString *)description { - return [NSString stringWithFormat:@"%@: adaptorChannel: %@", - [super description], self->adChannel]; + NSMutableString *ms; + + ms = [NSMutableString stringWithCapacity:128]; + [ms appendFormat:@"<%@[0x%08X]:", NSStringFromClass([self class]), self]; + + if (self->fetchSpecification != nil) + [ms appendFormat:@" fspec=%@", self->fetchSpecification]; + if (self->adChannel != nil) + [ms appendFormat:@" channel=%@", self->adChannel]; + + [ms appendString:@">"]; + return ms; } @end /* EOAdaptorDataSource */ @@ -1057,6 +980,128 @@ static NSNotificationCenter *getNC(void ) { return [qual sqlExpressionWithAdaptor:adaptor attributes:attrs]; } +- (NSException *)_couldNotFindSortAttributeInAttributes:(NSArray *)_attrs + forSortOrdering:(EOSortOrdering *)_so +{ + return [[InvalidAttributeException alloc] + initWithFormat:@"could not find EOAttribute for SortOrdering" + @" %@ Attributes %@", _so, _attrs]; +} + +- (EOAttribute *)findAttributeForKey:(NSString *)key + inAttributes:(NSArray *)_attrs +{ + NSEnumerator *en; + EOAttribute *obj; + + key = [key lowercaseString]; + en = [_attrs objectEnumerator]; + while ((obj = [en nextObject]) != nil) { + if ([[[obj columnName] lowercaseString] isEqualToString:key]) + break; + } + return obj; +} + +- (NSString *)_orderByExprForAttributes:(NSArray *)_attrs + andPatchSelectList:(NSMutableString *)selectList + withChannel:(EOAdaptorChannel *)_adChan +{ + NSMutableString *orderByExpr; + NSEnumerator *enumerator = nil; + EOSortOrdering *sortOrdering = nil; + int orderCnt = 0; + EOAdaptor *adaptor; + + adaptor = [[_adChan adaptorContext] adaptor]; + + orderByExpr = nil; + enumerator = [[self->fetchSpecification sortOrderings] objectEnumerator]; + while ((sortOrdering = [enumerator nextObject]) != nil) { + SEL selector = NULL; + NSString *key = nil; + EOAttribute *keyAttr = nil; + int order = 0; /* 0 - not used; 1 - asc; 2 - desc */ + BOOL inSensitive = NO; + NSString *orderTmp = nil; + + if (orderByExpr == nil) + orderByExpr = [NSMutableString stringWithCapacity:64]; + else + [orderByExpr appendString:@", "]; + + if ((selector = [sortOrdering selector])) { + if (SEL_EQ(selector, EOCompareAscending)) + order = 1; + else if (SEL_EQ(selector, EOCompareDescending)) + order = 2; + else if (SEL_EQ(selector, EOCompareCaseInsensitiveAscending)) { + order = 1; + inSensitive = YES; + } + else if (SEL_EQ(selector, EOCompareCaseInsensitiveDescending)) { + order = 2; + inSensitive = YES; + } + } + key = [sortOrdering key]; + + if (key == nil || [key length] == 0) { + NSLog(@"WARNING[%s]: no key in sortordering %@", + __PRETTY_FUNCTION__, key); + continue; + } + { + EOAttribute *obj; + + key = [key lowercaseString]; + obj = [self findAttributeForKey:key inAttributes:_attrs]; + if (obj == nil) { + [self->__attributes release]; self->__attributes = nil; + [self->__qualifier release]; self->__qualifier = nil; +#if 0 // TODO: memleak in error case + [expression release]; expression = nil; +#endif + [self rollbackTransaction]; + + [[self _couldNotFindSortAttributeInAttributes:_attrs + forSortOrdering:sortOrdering] raise]; + return nil; + } + + keyAttr = obj; + } + key = [adaptor formatAttribute:keyAttr]; + orderTmp = [NSString stringWithFormat:@"order%d", orderCnt]; + orderCnt++; + [orderByExpr appendString:orderTmp]; + if (order == 1) + [orderByExpr appendString:@" ASC"]; + else if (order == 2) + [orderByExpr appendString:@" DESC"]; + + /* manipulate select expr */ + if (inSensitive) { + if ([[keyAttr valueClassName] isEqualToString:@"NSString"]) { + key = [NSString stringWithFormat:@"LOWER(%@)", key]; + } + else + NSLog(@"WARNING[%s]: inSensitive expression for no text attribute", + __PRETTY_FUNCTION__); + } + { + NSString *str = nil; + + str = [key stringByAppendingString:@" AS "]; + str = [str stringByAppendingString:orderTmp]; + str = [str stringByAppendingString:@", "]; + + [selectList insertString:str atIndex:0]; + } + } + return orderByExpr; +} + - (NSMutableString *)_selectListWithChannel:(EOAdaptorChannel *)_adChan { NSArray *attrs = nil; NSEnumerator *enumerator = nil; diff --git a/sope-gdl1/GDLAccess/Version b/sope-gdl1/GDLAccess/Version index 6053c6f7..3e648f95 100644 --- a/sope-gdl1/GDLAccess/Version +++ b/sope-gdl1/GDLAccess/Version @@ -1,3 +1,3 @@ # version file -SUBMINOR_VERSION:=44 +SUBMINOR_VERSION:=46 -- 2.39.5