mirror of
https://github.com/gnustep/libs-gdl2.git
synced 2025-02-21 18:40:51 +00:00
* *.h/m, *.h/m): Used #include instead of depricated #import. Avoid including entire library headers. Use export macro where applicable. * EOControl/GNUmakefile: Removed EOKeyValueCodingBase.m/h and EOUndoMananger.h. Added EOArrayDataSource.m/h, EODefines.h and EODepricated.h. * EOControl/EODefines.h: Updated for GDL2 & gnustep-make. * EOControl/EODebug.h: Updated. * EOControl/EODepricated.h: Updated for current state of GDL2. ([NSObject +flushClassKeyBindings]): Added declaration. ([EOClassDescription +setDelegate:]): Added declaration. ([EOClassDescription +delegate]): Added declaration. (EOUndoManager): Moved declaration of interface here. * EOControl/EOKeyValueCoding.m ([EOClassDescription +flushClassKeyBindings]): Added empty implementation. ([NSObject takeStoredValuesFromDictionary:]): Cache EONull instance and use it instead of isKindOfClass:. * EOControl/EOEditingContext.m ([EOEditingContext +initialize]): Tidied. ([EOEditingContest -deleteObject]): Use NSUndoManager instead of EOUndoManager. * EOControl/EOQualifier.m ([NSArray -filteredArrayUsingQualifier:]): Added minor optimization tweak. * EOControl/EOClassDescription.m: Removed inactive commented code. Added private declerations of EOAccess methods to avoid compiler warnings. ([EOClassDescription +initialize]): Tidied. ([EOClassDescription -classDescriptionForClass:]): Use GSObjCName() instead of objc runtime routines. * EOControl/EOFault.m: Exchanged direct usages of ObjC runtime routines with NS/GSObjCRuntime abstraction API. ([EOFault +superclass]): Ditto. ([EOFault +targetClassForFault:]): Ditto. ([EOFault -respondsToSelector:]): Ditto. ([EOFault +initialize]): Cache static class variable. ([EOFault +isKindOfClass]): Use static class variable. ([EOFault +handlerForFault:]): Ditto. ([EOFault +targetClassForFault:]): Ditto. ([EOFault -dealloc]): Ditto. * EOControl/EOGenericRecord.m: ([EOGenericRecord +initialize]): Tidied. * EOControl/EOKeyComparisonQualifier.m: Tidied documentation. * EOControl/EOKeyValueQualifier.m: Ditto. * EOControl/EONSAddOns.h/m: Added declarations to surpress compiler warnings. ([NSObject -eoCompareOnName:]): Adjusted casts to surpress compiler warnings. (GSUseStrictWO451Compatibility): Added function. (GDL2GlobalLock, GDL2GlobalRecursive): Ditto. * EOControl/EONull: Remove implementations for foundation libraries without key value coding and fully rely on NSNull. Added assertions in all intance methods as instances should never be created. ([EONull +allocWithZone:]) Corrected method name so it will actually be used. * EOControl/EOSortOrdering.m ([NSArray sortedArrayUsingKeyOrderArray:]): Tidied. ([NSMutableArray sortUsingKeyOrderArray:]): Ditto. ([EONull compareAscending:]): Sync with referencs implementation. ([EONull compareDescending:]): Ditto. ([EONull compareCaseInsensitiveAscending:]): Ditto. ([EONull compareCaseInsensitiveDescending:]): Ditto. * EOAccess/EOAdaptor.h: Added comment about API compatibility. * EOAccess/EOAdaptor.m ([EOAdaptor -contexts]): Return array of adaptor contexts rather tham GC-wrapper objects containing adaptor contexts. ([EOAdaptor -databaseEncoding]): Use GSEncodingName() instead of GetEncodingName(). * EOAccess/EODatabaseContext.m ([EODatabaseContext -_turnFault:gid:editingContext:isComplete:]): Use GSObjCClass() instead of trying to access isa by dereferencing from id with incorrect member. * EOAccess/EOModel.m ([EOModel -entityNames]): Sort returned array to insure comparable output. * EOAccess/EOSQLExpression.m ([EOSQLExpression sqlStringForArrayOfQualifiers:operation:]): Added cast to surpress compiler warning. * EOAccess/EOUtilities.m ([EOObjectStoreCoordinator setModelGroup:]): Ditto. * EOAccess/EORelationship.h ([EORelationship -docComment]): Added declaration. * EOAccess/GNUmakefile: Added EODefines.h and EODepricated.h. * Tools/*.m: Use RCS_ID macro. * Tools/EOAttribute+GSDoc.h: ([EOAttribute gsdocContentWithTagName:idPtr:]): Corrected Typo. * Tools/EOModel+GSDoc.h/m: ([EOModel gsdocContentSplittedByEntities:idPtr:]): Ditto. * Tools/EORelationship+GSDoc.m: ([EORelationship gsdocContentWithTagName:idPtr:]): Change variable type to supress compiler warnings. * Tools/eoutil.m (dump): Initialize variables to supress compiler warnings. * Tools/gsdoc-model.m: Include GSCategories.h to supress compiler warnings. (main): Added cast to supress compiler warning. Fixed typo in method invocation. 2003-03-25 Stephane Corthesy <stephane@sente.ch> * EOControl/EODefines.h: Added new file for export/win32 support. * EOControl/EODepricated.h: Added new file for depricated features. * EOControl/EOControl.h: Added EOArrayDataSource.h and EODefines.h. * EOControl/EOArrayDataSource.h/m: Added new files. Some methods (<NSCoding> and qualifier bindings) are empty stubs. * EOControl/EODebug.h: Use export macro instead of explicit extern for function and symbol declarations. * EOControl/EOGlobalID.h: Ditto. * EOControl/EONull.h: Ditto. * EOControl/EOObjectStore.h: Ditto. * EOControl/EOOrQualifier.m: Replaced autorelease by AUTORELEASE and fixed typo. * EOControl/EOQualifier.m ([NSArray -filteredArrayUsingQualifier:]): Implemented. * EOControl/EONSAddOns.m: Use volatile in some exception handlers (man longjmp for more info). * EOControl/EOSortOrdering.h/m ([EOSortOrdering -copyWithZone:]): Implemented <NSCopying>. ([EOSortOrdering -encodeWithKeyValueArchiver:]): Implemented. * EOAccess/EODefines.h: Added new file for export/win32 support. * EOAccess/EODepricated.h: Added new file for depricated features. * EOAccess/EOAccess.h: Added EODefines.h. * EOAccess/EOSQLExpression.h/m: Fixed typo for EOPrimaryKeyConstraintKey. * EOAccess/EOExpressionArray.h/m: Use volatile for variables usein in exception handlers. (man longjmp for more info) * EOAccess/EODatabase.h: Use export macro instead of explicit extern for function and symbol declarations. * EOAccess/EOEntity.h: Ditto. * EOAccess/EOModel.h: Ditto. * EOAccess/EOSchemaGeneration.h: Ditto. * EOAccess/EOSQLExpression.h: Ditto. * EOAccess/EOUtilities.h: Ditto. * Tools/eoutil.m (dump): Implemented use of -postinstall option. Corrected bug when getting adaptor's expression class. Renamed symbol EOPrimaryKeyContraintsKey into EOPrimaryKeyConstraintsKey. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@16298 72102866-910b-0410-8b05-ffd578937521
818 lines
25 KiB
Objective-C
818 lines
25 KiB
Objective-C
/**
|
|
EODatabaseChannel.m <title>EODatabaseChannel</title>
|
|
|
|
Copyright (C) 2000-2003 Free Software Foundation, Inc.
|
|
|
|
Author: Mirko Viviani <mirko.viviani@rccr.cremona.it>
|
|
Date: June 2000
|
|
|
|
Author: Manuel Guesdon <mguesdon@orange-concept.com>
|
|
Date: October 2000
|
|
|
|
$Revision$
|
|
$Date$
|
|
|
|
<abstract></abstract>
|
|
|
|
This file is part of the GNUstep Database Library.
|
|
|
|
<license>
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; see the file COPYING.LIB.
|
|
If not, write to the Free Software Foundation,
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
</license>
|
|
**/
|
|
|
|
#include "config.h"
|
|
|
|
RCS_ID("$Id$")
|
|
|
|
#ifndef NeXT_Foundation_LIBRARY
|
|
#include <Foundation/NSString.h>
|
|
#include <Foundation/NSArray.h>
|
|
#include <Foundation/NSDictionary.h>
|
|
#include <Foundation/NSEnumerator.h>
|
|
#include <Foundation/NSNotification.h>
|
|
#include <Foundation/NSException.h>
|
|
#include <Foundation/NSObjCRuntime.h>
|
|
#include <Foundation/NSDebug.h>
|
|
#else
|
|
#include <Foundation/Foundation.h>
|
|
#endif
|
|
|
|
#include <EOControl/EOEditingContext.h>
|
|
#include <EOControl/EOKeyValueCoding.h>
|
|
#include <EOControl/EOFetchSpecification.h>
|
|
#include <EOControl/EOClassDescription.h>
|
|
#include <EOControl/EOKeyGlobalID.h>
|
|
#include <EOControl/EOObjectStore.h>
|
|
#include <EOControl/EODebug.h>
|
|
|
|
#include <EOAccess/EODatabaseChannel.h>
|
|
#include <EOAccess/EODatabaseChannelPriv.h>
|
|
#include <EOAccess/EODatabaseContext.h>
|
|
#include <EOAccess/EODatabaseContextPriv.h>
|
|
#include <EOAccess/EODatabase.h>
|
|
|
|
#include <EOAccess/EOAdaptor.h>
|
|
#include <EOAccess/EOAdaptorChannel.h>
|
|
#include <EOAccess/EOAdaptorContext.h>
|
|
#include <EOAccess/EOEntity.h>
|
|
#include <EOAccess/EOAttribute.h>
|
|
#include <EOAccess/EORelationship.h>
|
|
#include <EOAccess/EOModel.h>
|
|
#include <EOAccess/EOAccessFault.h>
|
|
#include <EOAccess/EOSQLExpression.h>
|
|
#include <EOAccess/EOSQLQualifier.h>
|
|
|
|
|
|
@implementation EODatabaseChannel
|
|
|
|
+ (void)initialize
|
|
{
|
|
if (self == [EODatabaseChannel class])
|
|
{
|
|
[[NSNotificationCenter defaultCenter]
|
|
addObserver: self
|
|
selector: @selector(_registerDatabaseChannel:)
|
|
name: EODatabaseChannelNeededNotification
|
|
object: nil];
|
|
}
|
|
}
|
|
|
|
+ (void)_registerDatabaseChannel: (NSNotification *)notification
|
|
{
|
|
// TODO who release it ?
|
|
[[EODatabaseChannel alloc] initWithDatabaseContext: [notification object]];
|
|
}
|
|
|
|
+ (EODatabaseChannel*)databaseChannelWithDatabaseContext: (EODatabaseContext *)databaseContext
|
|
{
|
|
return [[[self alloc] initWithDatabaseContext: databaseContext] autorelease];
|
|
}
|
|
|
|
- (id) initWithDatabaseContext:(EODatabaseContext *)databaseContext
|
|
{
|
|
if ((self = [super init]))
|
|
{
|
|
ASSIGN(_databaseContext, databaseContext);
|
|
ASSIGN(_adaptorChannel, [[_databaseContext adaptorContext]
|
|
createAdaptorChannel]);
|
|
//TODO NO<<<<
|
|
[_adaptorChannel openChannel];
|
|
|
|
_fetchProperties = [NSMutableArray new];
|
|
_fetchSpecifications = [NSMutableArray new];
|
|
//NO>>>>>>>
|
|
[_databaseContext registerChannel: self];//should be in caller
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[_databaseContext unregisterChannel: self];
|
|
|
|
DESTROY(_databaseContext);
|
|
[_adaptorChannel closeChannel];
|
|
|
|
DESTROY(_adaptorChannel);
|
|
DESTROY(_currentEntity);
|
|
DESTROY(_currentEditingContext);
|
|
DESTROY(_fetchProperties);
|
|
DESTROY(_fetchSpecifications);
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)setCurrentEntity: (EOEntity *)entity
|
|
{
|
|
//OK
|
|
ASSIGN(_currentEntity, entity);
|
|
[self setEntity: entity];
|
|
}
|
|
|
|
- (void) setEntity: (EOEntity *)entity
|
|
{
|
|
//Near OK
|
|
NSArray *relationships = [entity relationships];
|
|
int i = 0;
|
|
int count = [relationships count];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"relationships=%@", relationships);
|
|
|
|
for (i = 0; i < count; i++)
|
|
{
|
|
EORelationship *relationship = [relationships objectAtIndex:i];
|
|
EOEntity *destinationEntity = [relationship destinationEntity];
|
|
EOModel *destinationEntityModel = [destinationEntity model];
|
|
EOEntity *entity = [relationship entity];
|
|
EOModel *entityModel = [entity model];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"relationship=%@", relationship);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"destinationEntity=%@", [destinationEntity name]);
|
|
|
|
NSAssert2(destinationEntity, @"No destinationEntity in relationship: %@ of entity %@",
|
|
relationship, [entity name]); //TODO: flattened relationship
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"entity=%@", [entity name]);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"destinationEntityModel=%p", destinationEntityModel);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"entityModel=%p", entityModel);
|
|
|
|
//If different: try to add destinationEntityModel
|
|
if (destinationEntityModel != entityModel)
|
|
{
|
|
EOEditingContext *editingContext = [self currentEditingContext];
|
|
//EODatabaseContext *databaseContext = [self databaseContext];
|
|
EOObjectStore *rootObjectStore = [editingContext rootObjectStore];
|
|
NSArray *cooperatingObjectStores =
|
|
[(EOObjectStoreCoordinator *)rootObjectStore
|
|
cooperatingObjectStores];
|
|
int cosCount = [cooperatingObjectStores count];
|
|
int i;
|
|
|
|
for (i = 0; i < cosCount; i++)
|
|
{
|
|
id objectStore = [cooperatingObjectStores objectAtIndex: i];
|
|
EODatabase *objectStoreDatabase = [objectStore database];
|
|
BOOL modelOK = [objectStoreDatabase
|
|
addModelIfCompatible: destinationEntityModel];
|
|
|
|
if (!modelOK)
|
|
{
|
|
/*EODatabase *dbDatabase = [[[EODatabase alloc]
|
|
initWithModel: destinationEntityModel] autorelease];*/
|
|
[self notImplemented: _cmd]; //TODO: finish it
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setCurrentEditingContext: (EOEditingContext*)context
|
|
{
|
|
//OK
|
|
EOCooperatingObjectStore *cooperatingObjectStore = [self databaseContext];
|
|
EOObjectStore *objectStore = [context rootObjectStore];
|
|
|
|
[(EOObjectStoreCoordinator*)objectStore
|
|
addCooperatingObjectStore: cooperatingObjectStore];
|
|
|
|
ASSIGN(_currentEditingContext, context);
|
|
}
|
|
|
|
- (void)selectObjectsWithFetchSpecification: (EOFetchSpecification *)fetch
|
|
editingContext: (EOEditingContext *)context
|
|
{
|
|
//should be OK
|
|
NSString *entityName = nil;
|
|
EODatabase *database = nil;
|
|
EOEntity *entity = nil;
|
|
EOQualifier *qualifier = nil;
|
|
EOQualifier *schemaBasedQualifier = nil;
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
entityName = [fetch entityName];
|
|
database = [_databaseContext database];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"database=%@", database);
|
|
|
|
entity = [database entityNamed: entityName];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"entity name=%@", [entity name]);
|
|
|
|
qualifier=[fetch qualifier];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"qualifier=%@", qualifier);
|
|
|
|
schemaBasedQualifier =
|
|
[(id<EOQualifierSQLGeneration>)qualifier
|
|
schemaBasedQualifierWithRootEntity: entity];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"schemaBasedQualifier=%@", schemaBasedQualifier);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"qualifier=%@", qualifier);
|
|
|
|
if (schemaBasedQualifier && schemaBasedQualifier != qualifier)
|
|
{
|
|
EOFetchSpecification *newFetch = nil;
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"fetch=%@", fetch);
|
|
//howto avoid copy of uncopiable qualifiers (i.e. those who contains uncopiable key or value)
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"fetch=%@", fetch);
|
|
|
|
newFetch = [[fetch copy] autorelease];
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"newFetch=%@", newFetch);
|
|
|
|
[newFetch setQualifier: schemaBasedQualifier];
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"newFetch=%@", newFetch);
|
|
|
|
fetch = newFetch;
|
|
}
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"%@ -- %@ 0x%x: isFetchInProgress=%s",
|
|
NSStringFromSelector(_cmd),
|
|
NSStringFromClass([self class]),
|
|
self,
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
[self _selectWithFetchSpecification:fetch
|
|
editingContext:context];
|
|
|
|
EOFLOGObjectFnStop();
|
|
}
|
|
|
|
- (id)fetchObject
|
|
{
|
|
//seems OK
|
|
EODatabase *database=nil;
|
|
id object = nil;
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
database = [_databaseContext database];
|
|
|
|
if (![self isFetchInProgress])
|
|
{
|
|
NSLog(@"No Fetch in progress");
|
|
NSDebugMLog(@"No Fetch in progress", "");
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
format: @"%@ -- %@ 0x%x: no fetch in progress",
|
|
NSStringFromSelector(_cmd),
|
|
NSStringFromClass([self class]),
|
|
self];
|
|
}
|
|
else
|
|
{
|
|
NSArray *propertiesToFetch=nil;
|
|
NSDictionary *row =nil;
|
|
|
|
NSAssert(_currentEditingContext, @"No current editing context");
|
|
NSAssert(_adaptorChannel,@"No adaptor channel");
|
|
|
|
propertiesToFetch = [self _propertiesToFetch];
|
|
|
|
EOFLOGObjectLevel(@"gsdb", @"Will fetchRow");
|
|
|
|
row = [_adaptorChannel fetchRowWithZone: NULL];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"row=%@", row);
|
|
//NSDebugMLog(@"TEST attributesToFetch=%@", [_currentEntity attributesToFetch]);
|
|
|
|
if (!row)
|
|
{
|
|
//TODO
|
|
//VERIFY
|
|
/*
|
|
if no more obj:
|
|
if transactionNestingLevel
|
|
adaptorContext transactionDidCommit
|
|
*/
|
|
}
|
|
else if([[_fetchSpecifications lastObject] fetchesRawRows]) // Testing against only one should be enough
|
|
{
|
|
object = [NSDictionary dictionaryWithDictionary:row];
|
|
}
|
|
else
|
|
{
|
|
BOOL isObjectNew = YES; //TODO used to avoid double fetch. We should see how to do when isRefreshingObjects == YES
|
|
EOGlobalID *gid;
|
|
NSDictionary *snapshot = nil;
|
|
|
|
NSAssert(_currentEntity, @"Not current Entity");
|
|
|
|
gid = [_currentEntity globalIDForRow: row
|
|
isFinal: YES];//OK
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"gid=%@", gid);
|
|
//NSDebugMLog(@"TEST attributesToFetch=%@",[_currentEntity attributesToFetch]);
|
|
|
|
object = [_currentEditingContext objectForGlobalID: gid]; //OK //nil
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"object=%@", object);
|
|
|
|
if (object)
|
|
isObjectNew = NO;
|
|
|
|
NSAssert(_databaseContext,@"No database context");
|
|
|
|
snapshot = [_databaseContext snapshotForGlobalID: gid]; //OK
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"snapshot=%@", snapshot);
|
|
//NSDebugMLog(@"TEST attributesToFetch=%@", [_currentEntity attributesToFetch]);
|
|
|
|
if (snapshot)
|
|
{
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"_delegateRespondsTo.shouldUpdateSnapshot=%d",
|
|
(int)_delegateRespondsTo.shouldUpdateSnapshot);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"[self isLocking]=%d",
|
|
(int)[self isLocking]);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"[self isRefreshingObjects]=%d",
|
|
(int)[self isRefreshingObjects]);
|
|
|
|
//mirko:
|
|
if((_delegateRespondsTo.shouldUpdateSnapshot == NO
|
|
&& ([self isLocking] == YES
|
|
|| [self isRefreshingObjects] == YES))
|
|
|| (_delegateRespondsTo.shouldUpdateSnapshot == YES
|
|
&& (row = (id)[_delegate databaseContext: _databaseContext
|
|
shouldUpdateCurrentSnapshot: snapshot
|
|
newSnapshot: row
|
|
globalID: gid
|
|
databaseChannel: self])))
|
|
{ // TODO delegate not correct !
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"Updating Snapshot=%@", snapshot);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"row=%@", row);
|
|
|
|
[_databaseContext recordSnapshot: row
|
|
forGlobalID: gid];
|
|
isObjectNew = YES; //TODO
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//NSDebugMLog(@"TEST attributesToFetch=%@", [_currentEntity attributesToFetch]);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"database class=%@", [database class]);
|
|
|
|
NSAssert(database, @"No database-context database");
|
|
|
|
[database recordSnapshot: row
|
|
forGlobalID: gid];
|
|
}
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"[self isRefreshingObjects]=%d",
|
|
(int)[self isRefreshingObjects]);
|
|
|
|
//From mirko
|
|
if ([self isRefreshingObjects] == YES)
|
|
{
|
|
[[NSNotificationCenter defaultCenter]
|
|
postNotificationName: EOObjectsChangedInStoreNotification
|
|
object: _databaseContext
|
|
userInfo: [NSDictionary dictionaryWithObject:
|
|
[NSArray arrayWithObject:gid]
|
|
forKey: EOUpdatedKey]]; //OK ?
|
|
}
|
|
|
|
if (!object)
|
|
{
|
|
EOClassDescription *entityClassDescripton = [_currentEntity classDescriptionForInstances];
|
|
|
|
object = [entityClassDescripton createInstanceWithEditingContext: _currentEditingContext
|
|
globalID: gid
|
|
zone: NULL];
|
|
|
|
//NSDebugMLog(@"TEST attributesToFetch=%@", [_currentEntity attributesToFetch]);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"object=%@", object);
|
|
NSAssert1(object, @"No Object. entityClassDescripton=%@", entityClassDescripton);
|
|
|
|
[_currentEditingContext recordObject: object
|
|
globalID: gid];
|
|
}
|
|
else if (object && [EOFault isFault: object])
|
|
{
|
|
EOAccessFaultHandler *handler = (EOAccessFaultHandler *)
|
|
[EOFault handlerForFault: object];
|
|
EOKeyGlobalID *handlerGID = (EOKeyGlobalID *)[handler globalID];
|
|
|
|
isObjectNew = YES; //TODO
|
|
|
|
[handlerGID isFinal]; //YES //TODO
|
|
[EOFault clearFault: object];
|
|
|
|
/*mirko:
|
|
[_databaseContext _removeBatchForGlobalID:gid
|
|
fault:obj];
|
|
|
|
[EOFault clearFault:obj];
|
|
*/
|
|
}
|
|
|
|
if (isObjectNew) //TODO
|
|
{
|
|
[EOObserverCenter suppressObserverNotification];
|
|
|
|
NS_DURING
|
|
{
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"Initialize %p", object);
|
|
|
|
[_currentEditingContext initializeObject: object
|
|
withGlobalID: gid
|
|
editingContext: _currentEditingContext];
|
|
}
|
|
NS_HANDLER
|
|
{
|
|
[EOObserverCenter enableObserverNotification];
|
|
[localException raise];
|
|
}
|
|
NS_ENDHANDLER;
|
|
|
|
[EOObserverCenter enableObserverNotification];
|
|
[object awakeFromFetchInEditingContext: _currentEditingContext];
|
|
}
|
|
}
|
|
}
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
return object;
|
|
};
|
|
|
|
- (BOOL)isFetchInProgress
|
|
{
|
|
//NSDebugMLog(@"TEST attributesToFetch=%@", [_currentEntity attributesToFetch]);
|
|
|
|
return [_adaptorChannel isFetchInProgress];
|
|
}
|
|
|
|
- (void)cancelFetch
|
|
{
|
|
EOFLOGObjectFnStart();
|
|
|
|
[self _cancelInternalFetch];
|
|
|
|
//TODO VERIFY - NO ??!!
|
|
[_adaptorChannel cancelFetch];
|
|
[_fetchProperties removeAllObjects];
|
|
[_fetchSpecifications removeAllObjects];
|
|
|
|
EOFLOGObjectFnStop();
|
|
}
|
|
|
|
- (EODatabaseContext *)databaseContext
|
|
{
|
|
return _databaseContext;
|
|
}
|
|
|
|
- (EOAdaptorChannel *)adaptorChannel
|
|
{
|
|
return _adaptorChannel;
|
|
}
|
|
|
|
- (BOOL)isRefreshingObjects
|
|
{
|
|
return _isRefreshingObjects;
|
|
}
|
|
|
|
- (void)setIsRefreshingObjects: (BOOL)yn
|
|
{
|
|
_isRefreshingObjects = yn;
|
|
}
|
|
|
|
- (BOOL)isLocking
|
|
{
|
|
return _isLocking;
|
|
}
|
|
|
|
- (void)setIsLocking: (BOOL)isLocking
|
|
{
|
|
_isLocking = isLocking;
|
|
}
|
|
|
|
- (void)setDelegate: delegate
|
|
{
|
|
_delegate = delegate;
|
|
|
|
_delegateRespondsTo.shouldSelectObjects =
|
|
[delegate respondsToSelector:@selector(databaseContext:shouldSelectObjectsWithFetchSpecification:databaseChannel:)];
|
|
_delegateRespondsTo.didSelectObjects =
|
|
[delegate respondsToSelector:@selector(databaseContext:didSelectObjectsWithFetchSpecification:databaseChannel:)];
|
|
_delegateRespondsTo.shouldUsePessimisticLock =
|
|
[delegate respondsToSelector:@selector(databaseContext:shouldUsePessimisticLockWithFetchSpecification: databaseChannel:)];
|
|
_delegateRespondsTo.shouldUpdateSnapshot =
|
|
[delegate respondsToSelector:@selector(databaseContext:shouldUpdateCurrentSnapshot:newSnapshot:globalID:databaseChannel:)];
|
|
}
|
|
|
|
- delegate
|
|
{
|
|
return _delegate;
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
@implementation EODatabaseChannel (EODatabaseChannelPrivate)
|
|
- (NSArray*) _propertiesToFetch
|
|
{
|
|
//OK
|
|
NSArray *attributesToFetch=nil;
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
attributesToFetch = [_currentEntity _attributesToFetch];
|
|
|
|
NSAssert(_currentEntity, @"No current Entity");
|
|
|
|
EOFLOGObjectFnStop();
|
|
|
|
return attributesToFetch;
|
|
}
|
|
|
|
-(void)_setCurrentEntityAndRelationshipWithFetchSpecification: (EOFetchSpecification *)fetch
|
|
{
|
|
//OK
|
|
NSString *entityName = [fetch entityName];
|
|
EODatabase *database = [_databaseContext database];
|
|
EOEntity *entity = [database entityNamed: entityName];
|
|
|
|
NSAssert1(entity, @"No Entity named %@", entityName);
|
|
|
|
[self setCurrentEntity: entity];
|
|
}
|
|
|
|
- (void) _buildNodeList:(id) param0
|
|
withParent:(id) param1
|
|
{
|
|
//TODO
|
|
[self notImplemented: _cmd];
|
|
}
|
|
|
|
- (id) currentEditingContext
|
|
{
|
|
return _currentEditingContext;
|
|
}
|
|
|
|
- (void) _cancelInternalFetch
|
|
{
|
|
//OK
|
|
EOFLOGObjectFnStart();
|
|
|
|
if ([_adaptorChannel isFetchInProgress])
|
|
{
|
|
[_adaptorChannel cancelFetch];
|
|
}
|
|
|
|
EOFLOGObjectFnStop();
|
|
}
|
|
|
|
- (void) _closeChannel
|
|
{
|
|
//TODO
|
|
[self notImplemented: _cmd];
|
|
}
|
|
|
|
- (void) _openChannel
|
|
{
|
|
//TODO
|
|
[self notImplemented: _cmd];
|
|
}
|
|
|
|
- (void)_selectWithFetchSpecification: (EOFetchSpecification *)fetch
|
|
editingContext: (EOEditingContext *)context
|
|
{
|
|
NSArray *propertiesToFetch = nil;
|
|
EOUpdateStrategy updateStrategy = EOUpdateWithOptimisticLocking;
|
|
BOOL fetchLocksObjects = NO;
|
|
BOOL refreshesRefetchedObjects = NO;
|
|
NSString *entityName = nil;
|
|
EODatabase *database = nil;
|
|
EOEntity *entity = nil;
|
|
NSArray *primaryKeyAttributes = nil;
|
|
NSDictionary *hints = nil;
|
|
EOModel *model = nil;
|
|
EOModelGroup *modelGroup = nil;
|
|
EOQualifier *qualifier = nil;
|
|
EOStoredProcedure *storedProcedure = nil;
|
|
id customQueryExpressionHint = nil;//TODO
|
|
EOSQLExpression *customQueryExpression = nil;//TODO
|
|
NSString *storedProcedureName = nil;
|
|
|
|
BOOL isDeep = NO;
|
|
NSArray *subEntities = nil;
|
|
NSDictionary *_hints = nil;
|
|
|
|
EOFLOGObjectFnStart();
|
|
|
|
_hints = [fetch _hints];
|
|
|
|
customQueryExpressionHint = [_hints objectForKey: @"EOCustomQueryExpressionHintKey"];//TODO use it
|
|
|
|
if (customQueryExpressionHint)
|
|
{
|
|
EOAdaptorContext *adaptorContext = nil;
|
|
EOAdaptor *adaptor = nil;
|
|
Class expressionClass = Nil;
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"customQueryExpressionHint=%@", customQueryExpressionHint);
|
|
|
|
adaptorContext = [_databaseContext adaptorContext];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"adaptorContext=%p", adaptorContext);
|
|
|
|
adaptor = [adaptorContext adaptor];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"adaptor=%p", adaptor);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"adaptor=%@", adaptor);
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"adaptor class=%@", [adaptor class]);
|
|
|
|
//TODO VERIFY
|
|
expressionClass = [adaptor expressionClass];
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"expressionClass=%@", expressionClass);
|
|
|
|
customQueryExpression = [expressionClass expressionForString:
|
|
customQueryExpressionHint];
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"customQueryExpression=%@", customQueryExpression);
|
|
}
|
|
|
|
[self setCurrentEditingContext: context]; //OK even if customQueryExpressionHintKey
|
|
[self _setCurrentEntityAndRelationshipWithFetchSpecification: fetch];
|
|
|
|
isDeep = [fetch isDeep]; //ret 1
|
|
|
|
if (!customQueryExpressionHint)
|
|
{
|
|
subEntities = [entity subEntities];
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"subEntities=%@", subEntities);
|
|
|
|
//Strange
|
|
{
|
|
NSMutableArray *array = nil;
|
|
|
|
array = [NSMutableArray arrayWithCapacity: 8];
|
|
|
|
if ([subEntities count] > 0 && isDeep)
|
|
{
|
|
//??
|
|
NSEnumerator *subEntitiesEnum = [subEntities objectEnumerator];
|
|
id subEntity = nil;
|
|
|
|
while ((subEntity = [subEntitiesEnum nextObject]))
|
|
{
|
|
EOFetchSpecification *fetchSubEntity;
|
|
|
|
fetchSubEntity = [fetch copy];
|
|
[fetchSubEntity setEntityName: [entity name]];
|
|
|
|
[array addObjectsFromArray:
|
|
[context objectsWithFetchSpecification:
|
|
fetchSubEntity]];
|
|
[fetchSubEntity release];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
propertiesToFetch = [self _propertiesToFetch];
|
|
updateStrategy = [_databaseContext updateStrategy];//Ret 0
|
|
fetchLocksObjects = [fetch locksObjects];
|
|
refreshesRefetchedObjects = [fetch refreshesRefetchedObjects];
|
|
entityName = [fetch entityName];
|
|
database = [_databaseContext database];
|
|
entity = [database entityNamed:entityName];
|
|
primaryKeyAttributes = [entity primaryKeyAttributes];
|
|
hints = [fetch hints]; // ret {}
|
|
storedProcedureName = [hints objectForKey: @"EOStoredProcedureNameHintKey"];//TODO use it
|
|
model = [entity model];
|
|
modelGroup = [model modelGroup]; //ret nil
|
|
//TODO if model gr
|
|
qualifier = [fetch qualifier]; //<EOAndQualifier> //Can be nil
|
|
|
|
if (customQueryExpression)
|
|
{
|
|
[_adaptorChannel evaluateExpression: customQueryExpression];
|
|
|
|
NSAssert([propertiesToFetch count] > 0, @"No properties to fetch");
|
|
|
|
[_adaptorChannel setAttributesToFetch: propertiesToFetch];
|
|
}
|
|
else
|
|
{
|
|
storedProcedure = [entity storedProcedureForOperation:
|
|
@"EOFetchWithPrimaryKeyProcedure"];
|
|
|
|
if (storedProcedure)
|
|
{
|
|
NSEmitTODO(); //TODO
|
|
|
|
[self notImplemented: _cmd];
|
|
}
|
|
|
|
NSAssert([propertiesToFetch count] > 0, @"No properties to fetch");
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"%@ -- %@ 0x%x: isFetchInProgress=%s",
|
|
NSStringFromSelector(_cmd),
|
|
NSStringFromClass([self class]),
|
|
self,
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
[_adaptorChannel selectAttributes: propertiesToFetch
|
|
fetchSpecification: fetch
|
|
lock: fetchLocksObjects
|
|
entity: entity];
|
|
}
|
|
|
|
EOFLOGObjectLevelArgs(@"gsdb", @"%@ -- %@ 0x%x: isFetchInProgress=%s",
|
|
NSStringFromSelector(_cmd),
|
|
NSStringFromClass([self class]),
|
|
self,
|
|
([self isFetchInProgress] ? "YES" : "NO"));
|
|
|
|
//TODO: verify
|
|
// (stephane@sente.ch) Uncommented end to allow rawRow fetches
|
|
if([_databaseContext updateStrategy] == EOUpdateWithPessimisticLocking
|
|
&& ![[_databaseContext adaptorContext] transactionNestingLevel])
|
|
[NSException raise:NSInvalidArgumentException
|
|
format:@"%@ -- %@ 0x%x: no transaction in progress",
|
|
NSStringFromSelector(_cmd),
|
|
NSStringFromClass([self class]),
|
|
self];
|
|
|
|
if(_delegateRespondsTo.shouldSelectObjects)
|
|
{
|
|
if(![_delegate databaseContext:_databaseContext
|
|
shouldSelectObjectsWithFetchSpecification:fetch
|
|
databaseChannel:self])
|
|
[NSException raise:EOGeneralDatabaseException
|
|
format:@"%@ -- %@ 0x%x: delegate refuses to select objects",
|
|
NSStringFromSelector(_cmd),
|
|
NSStringFromClass([self class]),
|
|
self];
|
|
};
|
|
|
|
[_fetchSpecifications addObject:fetch];
|
|
|
|
// [self setCurrentEntity:[[_databaseContext database]
|
|
// entityNamed:[fetch entityName]]];//done
|
|
// [self setCurrentEditingContext:context];//done
|
|
|
|
[self setIsLocking:([_databaseContext updateStrategy] ==
|
|
EOUpdateWithPessimisticLocking ?
|
|
YES :
|
|
[fetch locksObjects])];
|
|
[self setIsRefreshingObjects:[fetch refreshesRefetchedObjects]];
|
|
|
|
// attributesToFetch = [_currentEntity attributesToFetch];//done
|
|
|
|
// EOFLOGObjectLevelArgs(@"gsdb",@"[_adaptorChannel class]: %@",[_adaptorChannel class]);
|
|
// [_adaptorChannel selectAttributes:attributesToFetch
|
|
// fetchSpecification:fetch
|
|
// lock:_isLocking
|
|
// entity:_currentEntity];//done
|
|
|
|
[_fetchProperties addObjectsFromArray:[self _propertiesToFetch]];
|
|
|
|
if(_delegateRespondsTo.didSelectObjects)
|
|
[_delegate databaseContext:_databaseContext
|
|
didSelectObjectsWithFetchSpecification:fetch
|
|
databaseChannel:self];
|
|
|
|
|
|
EOFLOGObjectFnStop();
|
|
}
|
|
|
|
@end /* EODatabaseChannel */
|