4 Copyright (C) 1996 Free Software Foundation, Inc.
6 Author: Ovidiu Predescu <ovidiu@bx.logicnet.ro>
9 This file is part of the GNUstep Database Library.
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License as published by the Free Software Foundation; either
14 version 2 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Library General Public License for more details.
21 You should have received a copy of the GNU Library General Public
22 License along with this library; see the file COPYING.LIB.
23 If not, write to the Free Software Foundation,
24 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #import "EOAdaptorChannel.h"
29 #import "EOAttribute.h"
31 #import "EOAdaptorContext.h"
32 #import "EOSQLExpression.h"
33 #import "EOFExceptions.h"
35 @interface EOAdaptorChannel(Internals)
36 - (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs;
37 @end /* EOAdaptorChannel(Internals) */
39 @implementation EOAdaptorChannel
41 + (NSCalendarDate*)dateForAttribute:(EOAttribute*)attr
42 year:(int)year month:(unsigned)month day:(unsigned)day
43 hour:(unsigned)hour minute:(unsigned)minute second:(unsigned)second
46 NSTimeZone *serverTimeZone = [attr serverTimeZone];
47 NSTimeZone *clientTimeZone = [attr clientTimeZone];
51 if (serverTimeZone == nil) serverTimeZone = [NSTimeZone localTimeZone];
52 if (clientTimeZone == nil) clientTimeZone = [NSTimeZone localTimeZone];
54 date = AUTORELEASE([[NSCalendarDate allocWithZone:zone]
55 initWithYear:year month:month day:day hour:hour
56 minute:minute second:second timeZone:serverTimeZone]);
57 [date setTimeZone:clientTimeZone];
58 fmt = [attr calendarFormat];
59 [date setCalendarFormat:fmt ? fmt : [EOAttribute defaultCalendarFormat]];
63 - (id)initWithAdaptorContext:(EOAdaptorContext*)_adaptorContext {
64 ASSIGN(self->adaptorContext, _adaptorContext);
67 [self->adaptorContext channelDidInit:self];
70 [localException raise];
78 [self->adaptorContext channelWillDealloc:self];
79 RELEASE(self->adaptorContext);
83 /* open/close channel */
93 - (void)closeChannel {
94 if ([self isFetchInProgress])
101 - (Class)_adaptorExpressionClass {
102 return [[self->adaptorContext adaptor] expressionClass];
105 - (BOOL)_isNoRaiseOnModificationException:(NSException *)_exception {
106 /* for compatibility with non-X methods, translate some errors to a bool */
109 n = [_exception name];
110 if ([n isEqualToString:@"EOEvaluationError"])
112 if ([n isEqualToString:@"EODelegateRejects"])
118 - (NSException *)insertRowX:(NSDictionary *)row forEntity:(EOEntity *)entity {
119 EOSQLExpression *sqlexpr;
120 NSMutableDictionary *mrow = (id)row;
124 return [[ChannelIsNotOpenedException new] autorelease];
126 if ((row == nil) || (entity == nil)) {
127 return [NSException exceptionWithName:NSInvalidArgumentException
128 reason:@"row and entity arguments for "
129 @"insertRow:forEntity: must not be the nil object"
133 if ([self isFetchInProgress])
134 return [AdaptorIsFetchingException exceptionWithAdaptor:self];
136 if ([self->adaptorContext transactionNestingLevel] == 0)
137 return [NoTransactionInProgressException exceptionWithAdaptor:self];
139 if (delegateRespondsTo.willInsertRow) {
140 EODelegateResponse response;
142 mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]);
143 response = [delegate adaptorChannel:self
146 if (response == EODelegateRejects) {
147 return [NSException exceptionWithName:@"EODelegateRejects"
148 reason:@"delegate rejected insert"
151 if (response == EODelegateOverrides)
155 sqlexpr = [[[self->adaptorContext adaptor]
157 insertExpressionForRow:mrow
161 ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
165 if(delegateRespondsTo.didInsertRow)
166 [delegate adaptorChannel:self didInsertRow:mrow forEntity:entity];
171 - (NSException *)updateRowX:(NSDictionary *)row
172 describedByQualifier:(EOSQLQualifier *)qualifier
174 EOSQLExpression *sqlexpr = nil;
175 NSMutableDictionary *mrow = (id)row;
179 return [[ChannelIsNotOpenedException new] autorelease];
182 return [NSException exceptionWithName:NSInvalidArgumentException
184 @"row argument for updateRow:describedByQualifier: "
185 @"must not be the nil object"
189 if ([self isFetchInProgress])
190 return [AdaptorIsFetchingException exceptionWithAdaptor:self];
192 if ([self->adaptorContext transactionNestingLevel] == 0)
193 return [NoTransactionInProgressException exceptionWithAdaptor:self];
195 if (delegateRespondsTo.willUpdateRow) {
196 EODelegateResponse response;
198 mrow = AUTORELEASE([row mutableCopyWithZone:[row zone]]);
199 response = [delegate adaptorChannel:self
201 describedByQualifier:qualifier];
202 if (response == EODelegateRejects) {
203 return [NSException exceptionWithName:@"EODelegateRejects"
204 reason:@"delegate rejected update"
207 if (response == EODelegateOverrides)
211 sqlexpr = [[self _adaptorExpressionClass]
212 updateExpressionForRow:mrow
216 ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
217 if (ex != nil) return ex;
219 if (delegateRespondsTo.didUpdateRow) {
220 [delegate adaptorChannel:self
222 describedByQualifier:qualifier];
227 - (NSException *)deleteRowsDescribedByQualifierX:(EOSQLQualifier *)qualifier {
228 EOSQLExpression *sqlexpr = nil;
232 return [[ChannelIsNotOpenedException new] autorelease];
234 if ([self isFetchInProgress])
235 return [AdaptorIsFetchingException exceptionWithAdaptor:self];
237 if ([self->adaptorContext transactionNestingLevel] == 0)
238 return [NoTransactionInProgressException exceptionWithAdaptor:self];
240 if (delegateRespondsTo.willDeleteRows) {
241 EODelegateResponse response;
243 response = [delegate adaptorChannel:self
244 willDeleteRowsDescribedByQualifier:qualifier];
245 if (response == EODelegateRejects) {
246 return [NSException exceptionWithName:@"EODelegateRejects"
247 reason:@"delegate rejected delete"
250 if (response == EODelegateOverrides)
254 sqlexpr = [[self _adaptorExpressionClass]
255 deleteExpressionWithQualifier:qualifier
258 ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
259 if (ex != nil) return ex;
261 if (delegateRespondsTo.didDeleteRows)
262 [delegate adaptorChannel:self didDeleteRowsDescribedByQualifier:qualifier];
267 /* compatibility methods (DEPRECATED, use the ...X methods */
269 - (BOOL)selectAttributes:(NSArray *)attributes
270 describedByQualifier:(EOSQLQualifier *)qualifier
271 fetchOrder:(NSArray *)fetchOrder
276 ex = [self selectAttributesX:attributes describedByQualifier:qualifier
277 fetchOrder:fetchOrder lock:lockFlag];
280 if ([self _isNoRaiseOnModificationException:ex])
286 - (BOOL)insertRow:(NSDictionary *)_row forEntity:(EOEntity *)_entity {
289 ex = [self insertRowX:_row forEntity:_entity];
292 if ([self _isNoRaiseOnModificationException:ex])
298 - (BOOL)updateRow:(NSDictionary *)_row
299 describedByQualifier:(EOSQLQualifier *)_q
303 ex = [self updateRowX:_row describedByQualifier:_q];
306 if ([self _isNoRaiseOnModificationException:ex])
312 - (BOOL)deleteRowsDescribedByQualifier:(EOSQLQualifier *)_qualifier {
315 ex = [self deleteRowsDescribedByQualifierX:_qualifier];
318 if ([self _isNoRaiseOnModificationException:ex])
324 /* fetch operations */
326 - (NSException *)selectAttributesX:(NSArray *)attributes
327 describedByQualifier:(EOSQLQualifier *)qualifier
328 fetchOrder:(NSArray *)fetchOrder
332 EOSQLExpression *sqlexpr = nil;
333 NSMutableArray *mattrs = (NSMutableArray *)attributes;
334 NSMutableArray *mfetch = (NSMutableArray *)fetchOrder;
337 return [[ChannelIsNotOpenedException new] autorelease];
339 if (attributes == nil) {
340 return [NSException exceptionWithName:NSInvalidArgumentException
342 @"attributes argument for selectAttributes:"
343 @"describedByQualifier:fetchOrder:lock: "
344 @"must not be the nil object"
348 if ([self isFetchInProgress])
349 return [AdaptorIsFetchingException exceptionWithAdaptor:self];
351 if ([self->adaptorContext transactionNestingLevel] == 0)
352 return [NoTransactionInProgressException exceptionWithAdaptor:self];
354 if (delegateRespondsTo.willSelectAttributes) {
355 EODelegateResponse response;
357 mattrs = [[attributes mutableCopy] autorelease];
358 mfetch = [[fetchOrder mutableCopy] autorelease];
360 response = [delegate adaptorChannel:self
361 willSelectAttributes:mattrs
362 describedByQualifier:qualifier
365 if (response == EODelegateRejects) {
366 return [NSException exceptionWithName:@"EODelegateRejects"
367 reason:@"delegate rejected select"
370 if (response == EODelegateOverrides)
375 #warning DEBUG LOG, REMOVE!
376 [self logWithFormat:@"fetch qualifier: %@", qualifier];
379 sqlexpr = [[[self->adaptorContext adaptor]
381 selectExpressionForAttributes:attributes
384 fetchOrder:fetchOrder
387 ex = [self evaluateExpressionX:[sqlexpr expressionValueForContext:nil]];
391 if (delegateRespondsTo.didSelectAttributes) {
392 [delegate adaptorChannel:self
393 didSelectAttributes:mattrs
394 describedByQualifier:qualifier
401 - (NSArray *)describeResults {
402 [self subclassResponsibility:_cmd];
406 - (NSMutableDictionary *)fetchAttributes:(NSArray *)attributes
407 withZone:(NSZone *)_zone
409 NSMutableDictionary *row = nil;
412 [[ChannelIsNotOpenedException new] raise];
415 _zone = NSDefaultMallocZone();
417 if(![self isFetchInProgress])
418 [[AdaptorIsNotFetchingException exceptionWithAdaptor:self] raise];
420 if(delegateRespondsTo.willFetchAttributes) {
421 row = [delegate adaptorChannel:self
422 willFetchAttributes:attributes
426 /* NOTE: primaryFetchAttributes:withZone: have to set the isFetchInProgress
429 row = [self primaryFetchAttributes:attributes withZone:_zone];
432 if(delegateRespondsTo.didFetchAttributes)
433 row = [delegate adaptorChannel:self
434 didFetchAttributes:row
436 if(delegateRespondsTo.didChangeResultSet)
437 [delegate adaptorChannelDidChangeResultSet:self];
440 /* Do not set here the isFetchInProgress status since only subclasses
441 can know whether there are more SELECT commands to be executed.
442 Setting the status here to NO will overwrite the adaptor subclass
444 if(delegateRespondsTo.didFinishFetching)
445 [delegate adaptorChannelDidFinishFetching:self];
450 - (BOOL)isFetchInProgress {
451 return self->isFetchInProgress;
454 - (void)cancelFetch {
456 [[ChannelIsNotOpenedException new] raise];
458 self->isFetchInProgress = NO;
461 - (NSMutableDictionary *)dictionaryWithObjects:(id *)objects
462 forAttributes:(NSArray *)attributes zone:(NSZone *)zone
464 [self notImplemented:_cmd];
468 - (NSMutableDictionary*)primaryFetchAttributes:(NSArray *)attributes
469 withZone:(NSZone *)zone
471 [self subclassResponsibility:_cmd];
475 - (BOOL)evaluateExpression:(NSString *)anExpression {
476 [self subclassResponsibility:_cmd];
479 - (NSException *)evaluateExpressionX:(NSString *)_sql {
486 ok = [self evaluateExpression:_sql];
488 ex = [localException retain];
491 if (ex) return [ex autorelease];
494 return [NSException exceptionWithName:@"EOEvaluationError"
495 reason:@"could not evaluate SQL expression"
499 - (EOAdaptorContext *)adaptorContext {
500 return self->adaptorContext;
503 - (EOModel *)describeModelWithTableNames:(NSArray *)tableNames {
504 [self subclassResponsibility:_cmd];
508 - (NSArray *)describeTableNames {
509 [self subclassResponsibility:_cmd];
513 - (BOOL)readTypesForEntity:(EOEntity*)anEntity {
514 [self subclassResponsibility:_cmd];
518 - (BOOL)readTypeForAttribute:(EOAttribute*)anAttribute {
519 [self subclassResponsibility:_cmd];
526 return self->delegate;
529 - (void)setDelegate:(id)_delegate {
530 self->delegate = _delegate;
532 delegateRespondsTo.willInsertRow =
533 [delegate respondsToSelector:
534 @selector(adaptorChannel:willInsertRow:forEntity:)];
535 delegateRespondsTo.didInsertRow =
536 [delegate respondsToSelector:
537 @selector(adaptorChannel:didInsertRow:forEntity:)];
538 delegateRespondsTo.willUpdateRow =
539 [delegate respondsToSelector:
540 @selector(adaptorChannel:willUpdateRow:describedByQualifier:)];
541 delegateRespondsTo.didUpdateRow =
542 [delegate respondsToSelector:
543 @selector(adaptorChannel:didUpdateRow:describedByQualifier:)];
544 delegateRespondsTo.willDeleteRows =
545 [delegate respondsToSelector:
546 @selector(adaptorChannel:willDeleteRowsDescribedByQualifier:)];
547 delegateRespondsTo.didDeleteRows =
548 [delegate respondsToSelector:
549 @selector(adaptorChannel:didDeleteRowsDescribedByQualifier:)];
550 delegateRespondsTo.willSelectAttributes =
551 [delegate respondsToSelector:
552 @selector(adaptorChannel:willSelectAttributes:
553 describedByQualifier:fetchOrder:lock:)];
554 delegateRespondsTo.didSelectAttributes =
555 [delegate respondsToSelector:
556 @selector(adaptorChannel:didSelectAttributes:
557 describedByQualifier:fetchOrder:lock:)];
558 delegateRespondsTo.willFetchAttributes =
559 [delegate respondsToSelector:
560 @selector(adaptorChannel:willFetchAttributes:withZone:)];
561 delegateRespondsTo.didFetchAttributes =
562 [delegate respondsToSelector:
563 @selector(adaptorChannel:didFetchAttributes:withZone:)];
564 delegateRespondsTo.didChangeResultSet =
565 [delegate respondsToSelector:
566 @selector(adaptorChannelDidChangeResultSet:)];
567 delegateRespondsTo.didFinishFetching =
568 [delegate respondsToSelector:
569 @selector(adaptorChannelDidFinishFetching:)];
570 delegateRespondsTo.willEvaluateExpression =
571 [delegate respondsToSelector:
572 @selector(adaptorChannel:willEvaluateExpression:)];
573 delegateRespondsTo.didEvaluateExpression =
574 [delegate respondsToSelector:
575 @selector(adaptorChannel:didEvaluateExpression:)];
578 - (void)setDebugEnabled:(BOOL)flag {
579 self->debugEnabled = flag;
582 - (BOOL)isDebugEnabled {
583 return self->debugEnabled;
589 @end /* EOAdaptorChannel */
591 #import <EOControl/EOFetchSpecification.h>
593 @implementation EOAdaptorChannel(PrimaryKeyGeneration) // new in EOF2
595 - (NSDictionary *)primaryKeyForNewRowWithEntity:(EOEntity *)_entity {
599 @end /* EOAdaptorChannel(PrimaryKeyGeneration) */
601 @implementation EOAdaptorChannel(EOF2Additions)
603 - (void)selectAttributes:(NSArray *)_attributes
604 fetchSpecification:(EOFetchSpecification *)_fspec
606 entity:(EOEntity *)_entity
611 q = (EOSQLQualifier *)[_fspec qualifier];
613 isOk = [self selectAttributes:_attributes
614 describedByQualifier:q
615 fetchOrder:[_fspec sortOrderings]
618 [NSException raise:@"Select failed"
619 format:@"could not select attributes for fetch spec"];
623 - (void)setAttributesToFetch:(NSArray *)_attributes {
624 [self notImplemented:_cmd];
626 - (NSArray *)attributesToFetch {
627 NSLog(@"ERROR(%s): subclasses must override this method!",
628 __PRETTY_FUNCTION__);
632 - (NSMutableDictionary *)fetchRowWithZone:(NSZone *)_zone {
633 return [self fetchAttributes:[self attributesToFetch] withZone:_zone];
636 @end /* EOAdaptorChannel(EOF2Additions) */
638 @implementation EOAdaptorChannel(Internals)
640 - (NSArray *)_sortAttributesForSelectExpression:(NSArray *)_attrs {
644 @end /* EOAdaptorChannel(Internals) */