Author: mguesdon
Date: Thu May 22 20:31:05 2014
New Revision: 37905
URL: http://svn.gna.org/viewcvs/gnustep?rev=37905&view=rev
Log:
* EOAccess/EODatabaseContext.m
implement _objectFaultWithSnapshot:relationship:editingContext:
fix -initializeObject:row:entity:editingContext:
finish implementation of -_obtainOpenChannel
implement -_forceDisconnect
fix -_openChannelWithLoginPanel:
implement -_verifyNoChangesToReadonlyEntity:
* EOAccess/EOAttributePriv.h
add -_isNonUpdateable
add -_isPrimaryKeyClassProperty
add _flags.isNonUpdateable
add _flags.isNonUpdateableInitialized
* EOAccess/EOAttribute.m
add -_isNonUpdateable
add -_isPrimaryKeyClassProperty
Modified:
libs/gdl2/trunk/ChangeLog
libs/gdl2/trunk/EOAccess/EOAttribute.h
libs/gdl2/trunk/EOAccess/EOAttribute.m
libs/gdl2/trunk/EOAccess/EOAttributePriv.h
libs/gdl2/trunk/EOAccess/EODatabaseContext.m
Modified: libs/gdl2/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/gdl2/trunk/ChangeLog?rev=37905&r1=37904&r2=37905&view=diff
==============================================================================
--- libs/gdl2/trunk/ChangeLog (original)
+++ libs/gdl2/trunk/ChangeLog Thu May 22 20:31:05 2014
@@ -1,3 +1,19 @@
+2014-05-22 Manuel Guesdon <[email protected]>
+ * EOAccess/EODatabaseContext.m
+ implement _objectFaultWithSnapshot:relationship:editingContext:
+ fix -initializeObject:row:entity:editingContext:
+ finish implementation of -_obtainOpenChannel
+ implement -_forceDisconnect
+ fix -_openChannelWithLoginPanel:
+ implement -_verifyNoChangesToReadonlyEntity:
+ * EOAccess/EOAttributePriv.h
+ add -_isNonUpdateable
+ add -_isPrimaryKeyClassProperty
+ add _flags.isNonUpdateable
+ add _flags.isNonUpdateableInitialized
+ * EOAccess/EOAttribute.m
+ add -_isNonUpdateable
+ add -_isPrimaryKeyClassProperty
2014-05-22 Manuel Guesdon <[email protected]>
* EOAdaptors/PostgreSQLAdaptor/PostgreSQLChannel.m:
fix newValueForDateTypeLengthAttribute
Modified: libs/gdl2/trunk/EOAccess/EOAttribute.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/gdl2/trunk/EOAccess/EOAttribute.h?rev=37905&r1=37904&r2=37905&view=diff
==============================================================================
--- libs/gdl2/trunk/EOAccess/EOAttribute.h (original)
+++ libs/gdl2/trunk/EOAccess/EOAttribute.h Thu May 22 20:31:05 2014
@@ -96,7 +96,9 @@
unsigned int isParentAnEOEntity:1;
unsigned int protoOverride:EOATTRIBUTE_PROTO_OVERRIDE_BITS_COUNT;
unsigned int isAttributeValueInitialized:1;
- unsigned int unused : 10;
+ unsigned int isNonUpdateable;
+ unsigned int isNonUpdateableInitialized;
+ unsigned int unused : 8;
} _flags;
unsigned int extraRefCount;
Modified: libs/gdl2/trunk/EOAccess/EOAttribute.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/gdl2/trunk/EOAccess/EOAttribute.m?rev=37905&r1=37904&r2=37905&view=diff
==============================================================================
--- libs/gdl2/trunk/EOAccess/EOAttribute.m (original)
+++ libs/gdl2/trunk/EOAccess/EOAttribute.m Thu May 22 20:31:05 2014
@@ -1035,6 +1035,7 @@
[self willChange];
_flags.isReadOnly = yn;
[self _setOverrideForKeyEnum: EOAttributeProtoOverrideBits_readOnly];
+ _flags.isNonUpdateableInitialized = NO;
}
}
@@ -2211,6 +2212,25 @@
return _sourceToDestinationKeyMap;
}
+-(BOOL)_isNonUpdateable
+{
+ if (!_flags.isNonUpdateableInitialized)
+ {
+ _flags.isNonUpdateable = ([self isReadOnly] || [self
_isPrimaryKeyClassProperty]);
+ _flags.isNonUpdateableInitialized = YES;
+ }
+ return _flags.isNonUpdateable;
+}
+
+-(BOOL)_isPrimaryKeyClassProperty
+{
+ NSArray* pkAttrs = [_parent primaryKeyAttributes];
+ if ([pkAttrs containsObject:self]
+ && [[_parent classProperties]containsObject:self])
+ return YES;
+ else
+ return NO;
+}
@end
Modified: libs/gdl2/trunk/EOAccess/EOAttributePriv.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/gdl2/trunk/EOAccess/EOAttributePriv.h?rev=37905&r1=37904&r2=37905&view=diff
==============================================================================
--- libs/gdl2/trunk/EOAccess/EOAttributePriv.h (original)
+++ libs/gdl2/trunk/EOAccess/EOAttributePriv.h Thu May 22 20:31:05 2014
@@ -65,6 +65,9 @@
- (void)_setValuesFromTargetAttribute;
-(void)_setSourceToDestinationKeyMap:(NSDictionary*)map;
-(NSDictionary*) _sourceToDestinationKeyMap;
+
+-(BOOL)_isNonUpdateable;
+-(BOOL)_isPrimaryKeyClassProperty;
@end
@interface EOAttribute (EOAttributePrivate2)
Modified: libs/gdl2/trunk/EOAccess/EODatabaseContext.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/gdl2/trunk/EOAccess/EODatabaseContext.m?rev=37905&r1=37904&r2=37905&view=diff
==============================================================================
--- libs/gdl2/trunk/EOAccess/EODatabaseContext.m (original)
+++ libs/gdl2/trunk/EOAccess/EODatabaseContext.m Thu May 22 20:31:05 2014
@@ -712,13 +712,7 @@
editingContext: (EOEditingContext *)context
isComplete: (BOOL)isComplete
{
- //OK
EOAccessFaultHandler *handler;
-
-
-
-
-
NSAssert(globalID, @"No globalID");
NSAssert1([globalID isKindOfClass: [EOKeyGlobalID class]],
@@ -747,7 +741,6 @@
[self _addBatchForGlobalID: (EOKeyGlobalID*)globalID
fault: object];
-
//TODO: use isComplete
}
@@ -5496,19 +5489,68 @@
return result;
}
+-(id)_fetchSingleObjectForEntity:(EOEntity*)entity
+ globalID:(EOGlobalID*)gid
+ editingContext:(EOEditingContext*)context
+{
+ id object=nil;
+ NSDictionary* pk = [entity primaryKeyForGlobalID:gid];
+ EOFetchSpecification* fetchSpec = [EOFetchSpecification
fetchSpecificationWithEntityName:[entity name]
+ qualifier: [entity
qualifierForPrimaryKey:pk]
+ sortOrderings: nil];
+ [fetchSpec setFetchLimit:1];
+ NSArray* objects = [self objectsWithFetchSpecification:fetchSpec
+ editingContext: context];
+ if ([objects count]==0)
+ {
+ [NSException raise: @"NSIllegalStateException"
+ format:@"The object with globalID %@ could not be found in
the database. This could be result of a referential integrity problem with the
database. An empty fault could not be created because the object's class could
not be determined (e.g. the GID is temporary or it is for an abstract entity).",
+ gid];
+ }
+ else
+ object=[objects objectAtIndex:0];
+
+ return object;
+}
+
+-(id)_objectFaultWithSnapshot:(NSDictionary*) snapshot
+ relationship:(EORelationship*) relationship
+ editingContext:(EOEditingContext*)context
+{
+ id objectFault=nil;
+ EOMutableKnownKeyDictionary *foreignKeyForSourceRow =
+ [relationship _foreignKeyForSourceRow: snapshot];
+
+ if ([foreignKeyForSourceRow containsObjectsNotIdenticalTo: GDL2_EONull])
+ {
+ EOEntity *destinationEntity = [relationship destinationEntity];
+ EOGlobalID *relRowGid = [destinationEntity
+ globalIDForRow: foreignKeyForSourceRow];
+
+ if ([[destinationEntity subEntities]count] > 0)
+ {
+ objectFault=[self _fetchSingleObjectForEntity:destinationEntity
+ globalID:relRowGid
+ editingContext:context];
+ }
+ else
+ {
+ objectFault=[context faultForGlobalID: relRowGid
+ editingContext: context];
+ }
+ }
+ return objectFault;
+}
+
- (void)initializeObject: (id)object
row: (NSDictionary*)row
entity: (EOEntity*)entity
editingContext: (EOEditingContext*)context
{
- //really near ok
NSArray *relationships = nil;
- NSArray *classPropertyAttributeNames = nil;
- NSUInteger count = 0;
+ NSArray *classPropertyAttributeNames = [entity classPropertyAttributeNames];
+ NSUInteger count = [classPropertyAttributeNames count];
IMP rowObjectForKeyIMP=NULL;
-
- classPropertyAttributeNames = [entity classPropertyAttributeNames];
- count = [classPropertyAttributeNames count];
//row is usuallly a EOMutableKnownKeyDictionary so will use
EOMKKD_objectForKeyWithImpPtr
@@ -5521,143 +5563,54 @@
@"Object is a fault. call -methodForSelector: on it is a bad
idea");
for (i = 0; i < count; i++)
- {
- id key = GDL2_ObjectAtIndexWithImp(classPropertyAttributeNames,oaiIMP,i);
- id value = nil;
-
-
- value = EOMKKD_objectForKeyWithImpPtr(row,&rowObjectForKeyIMP,key);
-
- if (value == GDL2_EONull)
- value = nil;
-
- [object takeStoredValue:value
- forKey:key];
- }
+ {
+ id key =
GDL2_ObjectAtIndexWithImp(classPropertyAttributeNames,oaiIMP,i);
+ id value = EOMKKD_objectForKeyWithImpPtr(row,&rowObjectForKeyIMP,key);
+
+ if (value == GDL2_EONull)
+ value = nil;
+
+ [object takeStoredValue:value
+ forKey:key];
+ }
};
- relationships = [entity _relationshipsToFaultForRow: row];
-
-
-
+ relationships = [entity _relationshipsToFaultForRow: row];
count = [relationships count];
if (count>0)
- {
- NSUInteger i=0;
- IMP oaiIMP=[relationships methodForSelector:@selector(objectAtIndex:)];
-
- NSAssert(!_isFault(object),
- @"Object is a fault. call -methodForSelector: on it is a bad
idea");
-
-
- for (i = 0; i < count; i++)
- {
- id relObject = nil;
- EORelationship *relationship =
GDL2_ObjectAtIndexWithImp(relationships,oaiIMP,i);
- NSString *relName = [relationship name];
-
-
- if ([relationship isToMany])
- {
- EOGlobalID *gid = [entity globalIDForRow: row];
-
- relObject = [self arrayFaultWithSourceGlobalID: gid
- relationshipName: relName
- editingContext: context];
- }
- else if ([relationship isFlattened])
- {
- // to one flattened relationship like
aRelationship.anotherRelationship...
-
- // I don't know how to handle this case.... May be we shouldn't treat
this as real property ??
- NSEmitTODO();
- relObject = nil;
- }
- else
- {
- EOMutableKnownKeyDictionary *foreignKeyForSourceRow = nil;
-
- foreignKeyForSourceRow = [relationship _foreignKeyForSourceRow: row];
-
- if (![foreignKeyForSourceRow
- containsObjectsNotIdenticalTo: GDL2_EONull])
- {
- NSEmitTODO();//TODO: what to do if rel is mandatory ?
- relObject = nil;
- }
- else
- {
- EOEntity *destinationEntity = [relationship destinationEntity];
- EOGlobalID *relRowGid = [destinationEntity
- globalIDForRow: foreignKeyForSourceRow];
-
-
-
- if ([(EOKeyGlobalID*)relRowGid areKeysAllNulls])
- NSWarnLog(@"All key of relRowGid %p (%@) are nulls",
- relRowGid,
- relRowGid);
-
- relObject = [context faultForGlobalID: relRowGid
- editingContext: context];
-
- NSDebugMLLog(@"EODatabaseContext", @"relObject=%p (%@)",
- relObject, [relObject class]);
- //end
- /*
- NSArray *joins = [(EORelationship *)prop joins];
- EOJoin *join;
- NSMutableDictionary *row;
- EOGlobalID *faultGID;
- int h, count;
- id value, realValue = nil;
-
- row = [NSMutableDictionary dictionaryWithCapacity:4];
-
- count = [joins count];
- for (h=0; h<count; h++)
- {
- join = [joins objectAtIndex:h];
-
- value = [snapshot objectForKey:[[join sourceAttribute]
- name]];
- if (value == null)
- realValue = nil;
- else
- realValue = value;
-
- [[prop validateValue:&realValue] raise];
-
- [row setObject:value
- forKey:[[join destinationAttribute]
- name]];
- }
-
- if (realValue || [prop isMandatory] == YES)
- {
- faultGID = [[(EORelationship *)prop destinationEntity]
- globalIDForRow:row];
-
- fault = [context objectForGlobalID:faultGID];
-
- if (fault == nil)
- fault = [context faultForGlobalID:faultGID
- editingContext:context];
- }
- else
- fault = nil;
-
- */
- }
- }
-
- [object takeStoredValue:relObject
- forKey:relName];
- }
- };
-
-
+ {
+ NSUInteger i=0;
+ IMP oaiIMP=[relationships methodForSelector:@selector(objectAtIndex:)];
+
+ NSAssert(!_isFault(object),
+ @"Object is a fault. call -methodForSelector: on it is a bad
idea");
+
+ for (i = 0; i < count; i++)
+ {
+ id relObject = nil;
+ EORelationship *relationship =
GDL2_ObjectAtIndexWithImp(relationships,oaiIMP,i);
+ NSString *relName = [relationship name];
+
+ if ([relationship isToMany])
+ {
+ EOGlobalID *gid = [entity globalIDForRow: row];
+
+ relObject = [self arrayFaultWithSourceGlobalID: gid
+ relationshipName: relName
+ editingContext: context];
+ }
+ else
+ {
+ relObject=[self _objectFaultWithSnapshot: row
+ relationship: relationship
+ editingContext: context];
+ }
+
+ [object takeStoredValue:relObject
+ forKey:relName];
+ }
+ }
}
- (void)forgetAllLocks
@@ -5745,11 +5698,19 @@
- (EODatabaseChannel*) _obtainOpenChannel
{
EODatabaseChannel *channel = [self availableChannel];
-
- if (![self _openChannelWithLoginPanel: channel])
- {
- NSEmitTODO();
- [self notImplemented: _cmd];//TODO
+ if (channel==nil)
+ {
+ [NSException raise: @"NSIllegalStateException"
+ format:@"%s: no database channel is available",
+ __PRETTY_FUNCTION__];
+
+ }
+ else if (![self _openChannelWithLoginPanel: channel])
+ {
+ [NSException raise: @"NSIllegalStateException"
+ format:@"%s: failed to open database channel",
+ __PRETTY_FUNCTION__];
+
}
return channel;
@@ -5757,21 +5718,69 @@
- (BOOL) _openChannelWithLoginPanel: (EODatabaseChannel*)databaseChannel
{
- // veridy: LoginPanel ???
+ BOOL result=NO;
EOAdaptorChannel *adaptorChannel = [databaseChannel adaptorChannel];
- if (![adaptorChannel isOpen]) //??
- {
- [adaptorChannel openChannel];
- }
-
- return [adaptorChannel isOpen];
+ if ([adaptorChannel isOpen])
+ result=YES;
+ else
+ {
+ NSException* exception=nil;
+ NS_DURING
+ {
+ [adaptorChannel openChannel];
+ }
+ NS_HANDLER
+ {
+ if (![[localException name]
isEqualToString:EOGeneralAdaptorException])
+ [localException raise];
+ else
+ NSLog(@"%@",localException);
+ }
+ NS_ENDHANDLER;
+
+ if ([adaptorChannel isOpen])
+ result=YES;
+ else
+ [exception raise];
+ }
+ return result;
}
- (void) _forceDisconnect
-{ // TODO
- NSEmitTODO();
- [self notImplemented: _cmd];
+{
+ EOAdaptorContext* adaptorContext = [self adaptorContext];
+ NSArray* channels = [adaptorContext channels];
+ NSArray* registeredChannels = [self registeredChannels];
+
+ int i = 0;
+ int c=[channels count];
+ for(i=0;i<c;i++)
+ {
+ NS_DURING
+ {
+ [[channels objectAtIndex:i] closeChannel];
+ }
+ NS_HANDLER
+ {
+ NSLog(@"%@",localException);
+ }
+ NS_ENDHANDLER;
+ }
+
+ c=[registeredChannels count];
+ for(i=0;i<c;i++)
+ {
+ NS_DURING
+ {
+ [self unregisterChannel:[registeredChannels objectAtIndex:i]];
+ }
+ NS_HANDLER
+ {
+ NSLog(@"%@",localException);
+ }
+ NS_ENDHANDLER;
+ }
}
@end
@@ -5795,25 +5804,63 @@
- (void) _verifyNoChangesToReadonlyEntity: (EODatabaseOperation*)dbOpe
{
- //TODO
- EOEntity *entity = nil;
-
-
-
- entity = [dbOpe entity];
-
-
-
+ EOEntity* entity = [dbOpe entity];
if ([entity isReadOnly])
{
- //?? exception I presume
- }
- else
- {
- [dbOpe databaseOperator]; //SoWhat
- }
-
-
+ switch([dbOpe databaseOperator])
+ {
+ case EOAdaptorInsertOperator:
+ [NSException raise: @"NSIllegalStateException"
+ format:@"cannot insert object: %@ that corresponds to
read-only entity: %@ in databaseContext %@",
+ [dbOpe object],
+ [entity name],
+ self];
+ break;
+ case EOAdaptorDeleteOperator:
+ [NSException raise: @"NSIllegalStateException"
+ format:@"cannot insert delete: %@ that corresponds to
read-only entity: %@ in databaseContext %@",
+ [dbOpe object],
+ [entity name],
+ self];
+ break;
+ case EOAdaptorUpdateOperator:
+ if (![[dbOpe dbSnapshot] isEqual:[dbOpe newRow]])
+ {
+ [NSException raise: @"NSIllegalStateException"
+ format:@"cannot update '%@' keys on object %@ that
corresponds to read-only entity: %@ in databaseContext %@",
+ [[dbOpe rowDiffsForAttributes:[entity attributes]]
allKeys],
+ [dbOpe object],
+ [entity name],
+ self];
+ }
+ break;
+ }
+ }
+ else if ([dbOpe databaseOperator] == EOAdaptorUpdateOperator
+ && [entity hasNonUpdateableAttributes])
+ {
+ NSArray* dbSnapshotKeys = [entity dbSnapshotKeys];
+ NSDictionary* dbSnapshot = [dbOpe dbSnapshot];
+ NSMutableDictionary* newRow = [dbOpe newRow];
+ int i=0;
+ int c=[dbSnapshotKeys count];
+ for(i=0;i<c;i++)
+ {
+ NSString* key = [dbSnapshotKeys objectAtIndex:i];
+ EOAttribute* attribute = [entity attributeNamed:key];
+ if ([attribute _isNonUpdateable]
+ && ![[dbSnapshot objectForKey:key] isEqual:[newRow
objectForKey:key]])
+ {
+ [NSException raise: @"NSIllegalStateException"
+ format:@"cannot update %@ '%@' on object: %@ that
corresponds to read-onlywof entity: %@ in databaseContext %@",
+ ([attribute isReadOnly] ? @"read-only key" :
@"primary-key"),
+ key,
+ [dbOpe object],
+ [entity name],
+ self];
+ }
+ }
+ }
}
- (void) _cleanUpAfterSave
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs