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.
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
@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)
@implementation EOAdaptorDataSource
+static Class NSCalendarDateClass = nil;
static NSNotificationCenter *nc = nil;
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 */
/* 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;
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;
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 "];
}
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;
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;
}
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;
}
}
- (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 */
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;