2 EODatabaseFaultResolver.m
4 Copyright (C) 1996 Free Software Foundation, Inc.
6 Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
9 Author: Helge Hess <helge.hess@mdlink.de>
12 This file is part of the GNUstep Database Library.
14 This library is free software; you can redistribute it and/or
15 modify it under the terms of the GNU Library General Public
16 License as published by the Free Software Foundation; either
17 version 2 of the License, or (at your option) any later version.
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Library General Public License for more details.
24 You should have received a copy of the GNU Library General Public
25 License along with this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #import "EODatabaseFaultResolver.h"
32 #import "EODatabaseChannel.h"
33 #import "EODatabaseContext.h"
35 #import "EODatabaseFault.h"
36 #import "EOSQLQualifier.h"
37 #import "EOGenericRecord.h"
39 @implementation EODatabaseFaultResolver
41 - (id)initWithDatabaseChannel:(EODatabaseChannel *)aChannel
43 targetClass:(Class)_targetClass
45 if ((self = [super init])) {
46 self->channel = aChannel;
47 self->targetClass = _targetClass;
49 self->faultReferences = 0;
58 - (EODatabaseChannel *)databaseChannel {
62 - (Class)targetClass; {
63 return self->targetClass;
66 - (NSDictionary *)primaryKey {
69 - (EOEntity *)entity {
72 - (EOSQLQualifier *)qualifier {
75 - (NSArray *)fetchOrder {
79 @end /* EODatabaseFaultResolver */
81 @implementation EOArrayFault
83 - (id)initWithQualifier:(EOSQLQualifier *)aQualifier
84 fetchOrder:(NSArray *)aFetchOrder
85 databaseChannel:(EODatabaseChannel *)aChannel
87 targetClass:(Class)_targetClass
90 if ((self = [super initWithDatabaseChannel:aChannel zone:aZone
91 targetClass:_targetClass])) {
92 self->qualifier = RETAIN(aQualifier);
93 self->fetchOrder = RETAIN(aFetchOrder);
95 NSAssert([(NSObject *)self->targetClass isKindOfClass:[NSArray class]],
96 @"target class of an array fault is not an array class");
102 RELEASE(self->qualifier);
103 RELEASE(self->fetchOrder);
107 - (EOEntity *)entity {
108 return [self->qualifier entity];
111 - (EOSQLQualifier *)qualifier {
112 return self->qualifier;
115 - (NSArray *)fetchOrder {
116 return self->fetchOrder;
119 - (void)completeInitializationOfObject:(id)_fault {
120 unsigned int oldRetainCount;
123 NSAssert([(NSObject *)self->targetClass isKindOfClass:[NSArray class]],
124 @"target class of an array fault is not an array class");
126 oldRetainCount = [_fault retainCount];
128 [EOFault clearFault:_fault];
129 NSAssert([(id)_fault init] == _fault, @"init modified fault reference ..");
131 NSAssert([_fault isKindOfClass:[NSArray class]],
132 @"resolved-object of an array fault is not of an array class");
134 if ([self->channel isFetchInProgress]) {
135 [NSException raise:NSInvalidArgumentException
136 format:@"attempt to fault with busy channel: %@", self];
139 inTransaction = [[self->channel databaseContext] transactionNestingLevel] > 0;
140 if (!inTransaction) {
141 if (![[self->channel databaseContext] beginTransaction]) {
142 [NSException raise:@"DBFaultResolutionException"
143 format:@"could not begin transaction to resolve fault !"];
147 if (![self->channel selectObjectsDescribedByQualifier:self->qualifier
148 fetchOrder:self->fetchOrder]) {
150 [[self->channel databaseContext] rollbackTransaction];
151 [NSException raise:@"DBFaultResolutionException"
152 format:@"select for fault failed !"];
158 while ((object = [self->channel fetchWithZone:zone])) {
159 if (![object isKindOfClass:[EOGenericRecord class]]) {
160 NSLog(@"Object is of class %@", NSStringFromClass([object class]));
163 NSAssert([object isKindOfClass:[EOGenericRecord class]],
164 @"fetched object is not a EOGenericRecord ..");
165 [(id)_fault addObject:object];
171 [self->channel cancelFetch];
173 if (!inTransaction) {
174 if (![[self->channel databaseContext] commitTransaction]) {
175 NSLog(@"WARNING: could not commit fault's transaction !");
176 [NSException raise:@"DBFaultResolutionException"
177 format:@"could not commit fault's transaction !"];
182 if ([fault retainCount] != oldRetainCount) {
183 NSLog(@"fault retain count does not match replacement (old=%d, new=%d)",
184 oldRetainCount, [fault retainCount]);
188 NSAssert([_fault retainCount] == oldRetainCount,
189 @"fault retain count does not match replacement's retain count");
192 - (NSString *)descriptionForObject:(id)_fault {
193 return [NSString stringWithFormat:
194 @"<Array fault 0x%x (qualifier=%@, order=%@, channel=%@)>",
195 _fault, qualifier, fetchOrder, channel];
198 @end /* EOArrayFault */
200 @implementation EOObjectFault
202 - (id)initWithPrimaryKey:(NSDictionary *)_key
203 entity:(EOEntity *)anEntity
204 databaseChannel:(EODatabaseChannel *)aChannel
206 targetClass:(Class)_targetClass
208 [super initWithDatabaseChannel:aChannel
210 targetClass:_targetClass];
211 self->entity = RETAIN(anEntity);
212 self->primaryKey = RETAIN(_key);
217 RELEASE(self->entity);
218 RELEASE(self->primaryKey);
222 - (NSDictionary*)primaryKey {
223 return self->primaryKey;
226 - (EOEntity *)entity {
230 - (void)completeInitializationOfObject:(id)_fault {
231 EOSQLQualifier *qualifier = nil;
232 BOOL channelIsOpen = YES;
233 BOOL inTransaction = YES;
236 if ([self->channel isFetchInProgress]) {
237 [NSException raise:NSInvalidArgumentException
238 format:@"attempt to fault with busy channel: %@", self];
242 [EOSQLQualifier qualifierForPrimaryKey:primaryKey entity:self->entity];
243 if (qualifier == nil) {
244 [NSException raise:NSInvalidArgumentException
245 format:@"could not build qualifier for fault: %@", self];
248 channelIsOpen = [self->channel isOpen];
249 if (!channelIsOpen) {
250 if (![self->channel openChannel])
254 inTransaction = [[self->channel databaseContext] transactionNestingLevel] != 0;
255 if (!inTransaction) {
256 if (![[self->channel databaseContext] beginTransaction]) {
257 if (!channelIsOpen) [self->channel closeChannel];
262 if (![self->channel selectObjectsDescribedByQualifier:qualifier fetchOrder:nil]) {
263 if (!inTransaction) {
264 [[self->channel databaseContext] rollbackTransaction];
265 if (!channelIsOpen) [self->channel closeChannel];
271 object = [self->channel fetchWithZone:zone];
275 [self->channel cancelFetch];
276 if (!inTransaction) [[self->channel databaseContext] rollbackTransaction];
277 if (!channelIsOpen) [self->channel closeChannel];
281 // Make sure we only fetched one object
282 if ([self->channel fetchWithZone:zone])
285 [self->channel cancelFetch];
287 if (!inTransaction) {
288 if (![[self->channel databaseContext] commitTransaction]) object = nil;
289 if (!channelIsOpen) [self->channel closeChannel];
293 if (object != _fault) {
294 if ([EOFault isFault:_fault])
295 [EOFault clearFault:_fault];
297 [(id)_fault unableToFaultWithPrimaryKey:primaryKey
299 databaseChannel:self->channel];
303 - (NSString *)descriptionForObject:(id)_fault {
304 return [NSString stringWithFormat:
305 @"<Object fault 0x%X "
306 @"(class=%@, entity=%@, key=%@, channel=%@)>",
308 NSStringFromClass(targetClass),
310 [primaryKey description],
311 [channel description]];
314 @end /* EOObjectFault */