* EOAccess/EODatabase.m

* EOAccess/EODatabase.h
add _doesReleaseUnreferencedSnapshots
add dummy for incrementSnapshotCountForGlobalID
add dummy for decrementSnapshotCountForGlobalID
add disableSnapshotRefcounting
* EOAccess/EODatabaseContext.m
retain EOAdaptorChannel created by adaptor
This is documented in WO 4.5.
Otherwise it gets closed after the request's
autorelease pool is drained.
I tested this on OSX with the BookStore example.
added some dummies for future implementation
refactor objectsWithFetchSpecification: editingContext:
refactor commitChanges
* EOAccess/EODatabaseChannel.m
reformat
* EOAdaptors/PostgreSQLAdaptor/PostgreSQLExpression.m
add include
* EOControl/EOGenericRecord.m
add [self willChange] in setValue:forUndefinedKey:
this will make saving changes possible for EOGenericRecord
otherwise it was just showing them in memory



git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gdl2/trunk@30675 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
dwetzel 2010-06-11 12:17:45 +00:00
parent 5c4b24e769
commit 7671304816
7 changed files with 535 additions and 1064 deletions

View file

@ -1,3 +1,28 @@
2010-06-11 David Wetzel <dave@turbocat.de>
* EOAccess/EODatabase.m
* EOAccess/EODatabase.h
add _doesReleaseUnreferencedSnapshots
add dummy for incrementSnapshotCountForGlobalID
add dummy for decrementSnapshotCountForGlobalID
add disableSnapshotRefcounting
* EOAccess/EODatabaseContext.m
retain EOAdaptorChannel created by adaptor
This is documented in WO 4.5.
Otherwise it gets closed after the request's
autorelease pool is drained.
I tested this on OSX with the BookStore example.
added some dummies for future implementation
refactor objectsWithFetchSpecification: editingContext:
refactor commitChanges
* EOAccess/EODatabaseChannel.m
reformat
* EOAdaptors/PostgreSQLAdaptor/PostgreSQLExpression.m
add include
* EOControl/EOGenericRecord.m
add [self willChange] in setValue:forUndefinedKey:
this will make saving changes possible for EOGenericRecord
otherwise it was just showing them in memory
2010-06-10 David Wetzel <dave@turbocat.de>
* EOControl/EOGenericRecord.h
* EOControl/EOGenericRecord.m

View file

@ -72,6 +72,10 @@ GDL2ACCESS_EXPORT NSTimeInterval EODistantPastTimeInterval;
- (id)initWithModel: (EOModel *)model;
- (void)incrementSnapshotCountForGlobalID:(EOGlobalID *)globalId;
- (void)decrementSnapshotCountForGlobalID:(EOGlobalID *)globalId;
+ (void)disableSnapshotRefcounting;
- (NSArray *)registeredContexts;
- (void)registerContext: (EODatabaseContext *)context;

View file

@ -75,6 +75,7 @@ RCS_ID("$Id$")
NSString *EOGeneralDatabaseException = @"EOGeneralDatabaseException";
NSTimeInterval EODistantPastTimeInterval = -603979776.0;
static BOOL _doesReleaseUnreferencedSnapshots = YES;
@implementation EODatabase
@ -173,6 +174,29 @@ static NSMutableArray *databaseInstances;
[super dealloc];
}
- (void)incrementSnapshotCountForGlobalID:(EOGlobalID *)globalId
{
if (!_doesReleaseUnreferencedSnapshots)
{
return;
}
GSOnceFLog(@"TODO: %s", __PRETTY_FUNCTION__);
}
- (void)decrementSnapshotCountForGlobalID:(EOGlobalID *)globalId
{
if (!_doesReleaseUnreferencedSnapshots)
{
return;
}
GSOnceFLog(@"TODO: %s", __PRETTY_FUNCTION__);
}
+ (void)disableSnapshotRefcounting
{
_doesReleaseUnreferencedSnapshots = NO;
}
- (NSArray *)registeredContexts
{
NSMutableArray *array = [NSMutableArray array];

View file

@ -224,13 +224,14 @@ RCS_ID("$Id$")
- (void)setCurrentEditingContext: (EOEditingContext*)context
{
//OK
EOCooperatingObjectStore *cooperatingObjectStore = [self databaseContext];
EOObjectStore *objectStore = [context rootObjectStore];
[(EOObjectStoreCoordinator*)objectStore
addCooperatingObjectStore: cooperatingObjectStore];
if (context) {
EOCooperatingObjectStore *cooperatingObjectStore = [self databaseContext];
EOObjectStore *objectStore = [context rootObjectStore];
[(EOObjectStoreCoordinator*)objectStore
addCooperatingObjectStore: cooperatingObjectStore];
}
ASSIGN(_currentEditingContext, context);
}
@ -302,189 +303,189 @@ RCS_ID("$Id$")
EODatabase *database=nil;
id object = nil;
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];
}
{
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);
if (!row)
{
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);
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);
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);
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
{
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];
EOFLOGObjectLevelArgs(@"gsdb", @"object=%@", object);
NSAssert1(object, @"No Object. entityClassDescripton=%@", entityClassDescripton);
EOEditingContext_recordObjectGlobalIDWithImpPtr(_currentEditingContext,
NULL,object,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];
}
}
//TODO
//VERIFY
/*
if no more obj:
if transactionNestingLevel
adaptorContext transactionDidCommit
*/
return nil;
}
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);
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);
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
{
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];
EOFLOGObjectLevelArgs(@"gsdb", @"object=%@", object);
NSAssert1(object, @"No Object. entityClassDescripton=%@", entityClassDescripton);
EOEditingContext_recordObjectGlobalIDWithImpPtr(_currentEditingContext,
NULL,object,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];
}
}
}
return object;
};

File diff suppressed because it is too large Load diff

View file

@ -51,6 +51,7 @@ RCS_ID("$Id$")
#ifndef GNUSTEP
#include <GNUstepBase/GNUstep.h>
#include <GNUstepBase/NSDebug+GNUstepBase.h>
#include <GNUstepBase/NSObject+GNUstepBase.h>
#endif
#include <EOControl/EONull.h>

View file

@ -772,6 +772,7 @@ inline BOOL infoForInstanceVariableWithImpPtr(id object,GDL2IMP_BOOL* impPtr,
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
[self willChange];
[_dictionary setObject:value
forKey:key];
}