From 19169e821dd6f8e8a22eee7e6786c70e1554667e Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Fri, 21 Oct 2011 14:57:57 +0000 Subject: [PATCH] Fix for bug #1442. See ChangeLog. Monotone-Parent: d7092dc459f63233bb9e0a7aadc3380b2682ed2a Monotone-Revision: f6c6bfab15922450127ccb9597bbc97468d695c0 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2011-10-21T14:57:57 Monotone-Branch: ca.inverse.sogo --- OGoContentStore/appointment-oracle.ocs | 39 +++++++++++ OGoContentStore/appointment.ocs | 41 +++++++++++- OGoContentStore/contact-oracle.ocs | 39 +++++++++++ OGoContentStore/contact.ocs | 41 +++++++++++- SOPE/GDLContentStore/ChangeLog | 13 ++++ SOPE/GDLContentStore/GCSFolder.h | 2 +- SOPE/GDLContentStore/GCSFolder.m | 93 +++++++++++++++++++------- SOPE/GDLContentStore/GCSFolderType.h | 9 +-- SOPE/GDLContentStore/GCSFolderType.m | 13 +++- 9 files changed, 256 insertions(+), 34 deletions(-) diff --git a/OGoContentStore/appointment-oracle.ocs b/OGoContentStore/appointment-oracle.ocs index ae5ad88ad..e5ab7197b 100644 --- a/OGoContentStore/appointment-oracle.ocs +++ b/OGoContentStore/appointment-oracle.ocs @@ -4,6 +4,45 @@ extractorClassName = "OCSiCalFieldExtractor"; fields = ( + { + columnName = c_name; + sqlType = "VARCHAR2(255)"; + allowsNull = NO; + isPrimaryKey = YES; + }, + { + columnName = c_content; + sqlType = "CLOB"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_creationdate; + sqlType = "INTEGER"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_lastmodified; + sqlType = "INTEGER"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_version; + sqlType = "INTEGER"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_deleted; + sqlType = "INTEGER"; + allowsNull = YES; + isPrimaryKey = NO; + } + ); + + quickFields = ( { columnName = c_name; sqlType = "VARCHAR2(255)"; diff --git a/OGoContentStore/appointment.ocs b/OGoContentStore/appointment.ocs index 3ad87705a..11384e48d 100644 --- a/OGoContentStore/appointment.ocs +++ b/OGoContentStore/appointment.ocs @@ -4,6 +4,45 @@ extractorClassName = "OCSiCalFieldExtractor"; fields = ( + { + columnName = c_name; + sqlType = "VARCHAR(255)"; + allowsNull = NO; + isPrimaryKey = YES; + }, + { + columnName = c_content; + sqlType = "VARCHAR(100000)"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_creationdate; + sqlType = "INT4"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_lastmodified; + sqlType = "INT4"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_version; + sqlType = "INT4"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_deleted; + sqlType = "INT4"; + allowsNull = YES; + isPrimaryKey = NO; + } + ); + + quickFields = ( { columnName = c_name; sqlType = "VARCHAR(255)"; @@ -114,6 +153,6 @@ columnName = c_nextalarm; sqlType = "INT"; allowsNull = YES; - }, + } ); } diff --git a/OGoContentStore/contact-oracle.ocs b/OGoContentStore/contact-oracle.ocs index 9ab1e9034..e0e8931f4 100644 --- a/OGoContentStore/contact-oracle.ocs +++ b/OGoContentStore/contact-oracle.ocs @@ -4,6 +4,45 @@ extractorClassName= "OCSContactFieldExtractor"; fields = ( + { + columnName = c_name; + sqlType = "VARCHAR2(255)"; + allowsNull = NO; + isPrimaryKey = YES; + }, + { + columnName = c_content; + sqlType = "CLOB"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_creationdate; + sqlType = "INTEGER"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_lastmodified; + sqlType = "INTEGER"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_version; + sqlType = "INTEGER"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_deleted; + sqlType = "INTEGER"; + allowsNull = YES; + isPrimaryKey = NO; + } + ); + + quickFields = ( { columnName = c_name; sqlType = "VARCHAR2(255)"; diff --git a/OGoContentStore/contact.ocs b/OGoContentStore/contact.ocs index a2f1af5e9..bac6f6147 100644 --- a/OGoContentStore/contact.ocs +++ b/OGoContentStore/contact.ocs @@ -4,6 +4,45 @@ extractorClassName= "OCSContactFieldExtractor"; fields = ( + { + columnName = c_name; + sqlType = "VARCHAR(255)"; + allowsNull = NO; + isPrimaryKey = YES; + }, + { + columnName = c_content; + sqlType = "VARCHAR(100000)"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_creationdate; + sqlType = "INT4"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_lastmodified; + sqlType = "INT4"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_version; + sqlType = "INT4"; + allowsNull = NO; + isPrimaryKey = NO; + }, + { + columnName = c_deleted; + sqlType = "INT4"; + allowsNull = YES; + isPrimaryKey = NO; + } + ); + + quickFields = ( { columnName = c_name; sqlType = "VARCHAR(255)"; @@ -51,7 +90,7 @@ allowsNull = YES; }, { - columnName = c_telephoneNumber; + columnName = c_telephonenumber; sqlType = "VARCHAR(255)"; allowsNull = YES; }, diff --git a/SOPE/GDLContentStore/ChangeLog b/SOPE/GDLContentStore/ChangeLog index b22ce9cb4..155d4e62a 100644 --- a/SOPE/GDLContentStore/ChangeLog +++ b/SOPE/GDLContentStore/ChangeLog @@ -1,3 +1,16 @@ +2011-10-21 Francis Lachapelle + + * GCSFolder.m + (_generateUpdateStatementForRow:adaptor:fields:tableName:whereColumn:isEqualTo:andColumn:isEqualTo:): + this method now uses the formatValue:forAttribute: method from the + database adaptor to benefit from the proper formatting depending + on the column type. + (-initWithPath:primaryKey:folderTypeName:folderType:location:quickLocation:aclLocation:folderManager:): + load the content field names from the GCSFolderType object. + + * GCSFolderType.m (-initWithPropertyList:): the content table + structure is now part of the plist (.ocs) file. + 2011-10-03 Francis Lachapelle * GCSFolder.m (-updateQuickFields:whereColumn:isEqualTo:): new diff --git a/SOPE/GDLContentStore/GCSFolder.h b/SOPE/GDLContentStore/GCSFolder.h index 4baf3f1dd..eb547219a 100644 --- a/SOPE/GDLContentStore/GCSFolder.h +++ b/SOPE/GDLContentStore/GCSFolder.h @@ -66,7 +66,7 @@ NSURL *quickLocation; NSURL *aclLocation; NSString *folderTypeName; - NSMutableArray *quickFieldNames; + NSMutableArray *quickFieldNames, *contentFieldNames; struct { int requiresFolderSelect:1; diff --git a/SOPE/GDLContentStore/GCSFolder.m b/SOPE/GDLContentStore/GCSFolder.m index 8a4be357a..c9cf89c61 100644 --- a/SOPE/GDLContentStore/GCSFolder.m +++ b/SOPE/GDLContentStore/GCSFolder.m @@ -1,7 +1,7 @@ /* Copyright (C) 2004-2007 SKYRIX Software AG Copyright (C) 2007 Helge Hess - Copyright (c) 2008-2009 Inverse inc. + Copyright (c) 2008-2011 Inverse inc. This file is part of OpenGroupware.org. @@ -30,6 +30,7 @@ #import #import #import +#import #import #import "GCSFieldInfo.h" @@ -60,7 +61,6 @@ static Class NSNumberClass = Nil; static Class NSCalendarDateClass = Nil; static GCSStringFormatter *stringFormatter = nil; -static NSArray *contentFieldNames = nil; + (void) initialize { @@ -72,13 +72,6 @@ static NSArray *contentFieldNames = nil; NSStringClass = [NSString class]; NSNumberClass = [NSNumber class]; NSCalendarDateClass = [NSCalendarDate class]; - if (!contentFieldNames) - { - contentFieldNames = [NSArray arrayWithObjects: @"c_content", - @"c_creationdate", @"c_lastmodified", - @"c_version", @"c_deleted", nil]; - [contentFieldNames retain]; - } stringFormatter = [GCSStringFormatter sharedFormatter]; } @@ -106,7 +99,7 @@ static NSArray *contentFieldNames = nil; if ((self = [super init])) { folderManager = [_fm retain]; folderInfo = [_ftype retain]; - fields = [[_ftype fields] objectEnumerator]; + fields = [[_ftype quickFields] objectEnumerator]; quickFieldNames = [NSMutableArray new]; while ((field = [fields nextObject])) { @@ -114,6 +107,14 @@ static NSArray *contentFieldNames = nil; if (![fieldName isEqualToString: @"c_name"]) [quickFieldNames addObject: fieldName]; } + + fields = [[_ftype fields] objectEnumerator]; + contentFieldNames = [NSMutableArray new]; + while ((field = [fields nextObject])) + { + fieldName = [field columnName]; + [contentFieldNames addObject: fieldName]; + } folderId = [_folderId copy]; folderName = [[_path lastPathComponent] copy]; @@ -163,6 +164,7 @@ static NSArray *contentFieldNames = nil; [location release]; [quickLocation release]; [quickFieldNames release]; + [contentFieldNames release]; [aclLocation release]; [folderTypeName release]; [super dealloc]; @@ -667,15 +669,20 @@ static NSArray *contentFieldNames = nil; } - (NSString *)_generateUpdateStatementForRow:(NSDictionary *)_row - tableName:(NSString *)_table - whereColumn:(NSString *)_colname isEqualTo:(id)_value - andColumn:(NSString *)_colname2 isEqualTo:(id)_value2 + adaptor:(EOAdaptor *)_adaptor + fields:(NSArray *)_fields + tableName:(NSString *)_table + whereColumn:(NSString *)_colname isEqualTo:(id)_value + andColumn:(NSString *)_colname2 isEqualTo:(id)_value2 { // TODO: move to NSDictionary category? NSMutableString *sql; NSArray *keys; + NSString *fieldName, *sqlType; + EOAttribute *attribute; + id value; unsigned i, count; - + if (_row == nil || _table == nil) return nil; @@ -684,18 +691,30 @@ static NSArray *contentFieldNames = nil; sql = [NSMutableString stringWithCapacity:512]; [sql appendString:@"UPDATE "]; [sql appendString:_table]; - [sql appendString:@" SET "]; + for (i = 0, count = [keys count]; i < count; i++) { - id value; + fieldName = [keys objectAtIndex:i]; + sqlType = [self _sqlTypeForColumn: fieldName withFieldInfos: _fields]; - value = [_row objectForKey:[keys objectAtIndex:i]]; - value = [self _formatRowValue:value]; - - if (i != 0) [sql appendString:@", "]; - [sql appendString:[keys objectAtIndex:i]]; - [sql appendString:@" = "]; - [sql appendString:value]; + if (sqlType) + { + value = [_row objectForKey: fieldName]; + attribute = AUTORELEASE([[EOAttribute alloc] init]); + [attribute setName: fieldName]; + [attribute setColumnName: fieldName]; + [attribute setExternalType: sqlType]; + + if (i != 0) [sql appendString:@", "]; + [sql appendString:fieldName]; + [sql appendString:@" = "]; + [sql appendString:[_adaptor formatValue: value forAttribute: attribute]]; + } + else + { + [self errorWithFormat:@"%s: no type found for column name %@", + __PRETTY_FUNCTION__, fieldName]; + } } [sql appendString:@" WHERE "]; @@ -713,6 +732,26 @@ static NSArray *contentFieldNames = nil; return sql; } +- (NSString *) _sqlTypeForColumn: (NSString *) _field withFieldInfos: (NSArray *) _fields +{ + NSString *sqlType; + NSEnumerator *fields; + GCSFieldInfo *fieldInfo; + + sqlType = nil; + fields = [_fields objectEnumerator]; + while ((fieldInfo = [fields nextObject])) + { + if ([[fieldInfo columnName] caseInsensitiveCompare: _field] == NSOrderedSame) + { + sqlType = [fieldInfo sqlType]; + break; + } + } + + return sqlType; +} + - (EOEntity *) _entityWithName: (NSString *) _name { EOAttribute *attribute; @@ -749,7 +788,6 @@ static NSArray *contentFieldNames = nil; { EOEntity *entity; EOAttribute *attribute; - GCSFieldInfo *field; NSEnumerator *fields; NSString *fieldName; @@ -956,6 +994,8 @@ static NSArray *contentFieldNames = nil; isEqualTo: _name andColumn: nil isEqualTo: nil entity: quickTableEntity]] : [quickChannel evaluateExpressionX: [self _generateUpdateStatementForRow: quickRow + adaptor: [[quickChannel adaptorContext] adaptor] + fields: [folderInfo quickFields] tableName: [self quickTableName] whereColumn: @"c_name" isEqualTo: _name andColumn: nil isEqualTo: nil]]); @@ -966,7 +1006,10 @@ static NSArray *contentFieldNames = nil; andColumn: (_baseVersion != 0 ? (id)@"c_version" : (id)nil) isEqualTo: (_baseVersion != 0 ? [NSNumber numberWithUnsignedInt:_baseVersion] : (NSNumber *)nil) entity: storeTableEntity]] - : [storeChannel evaluateExpressionX: [self _generateUpdateStatementForRow: contentRow tableName:[self storeTableName] + : [storeChannel evaluateExpressionX: [self _generateUpdateStatementForRow: contentRow + adaptor: [[storeChannel adaptorContext] adaptor] + fields: [folderInfo fields] + tableName:[self storeTableName] whereColumn: @"c_name" isEqualTo: _name andColumn: (_baseVersion != 0 ? (id)@"c_version" : (id)nil) isEqualTo: (_baseVersion != 0 ? [NSNumber numberWithUnsignedInt: _baseVersion] : (NSNumber *)nil)]]); diff --git a/SOPE/GDLContentStore/GCSFolderType.h b/SOPE/GDLContentStore/GCSFolderType.h index 369e06087..8a2e843ce 100644 --- a/SOPE/GDLContentStore/GCSFolderType.h +++ b/SOPE/GDLContentStore/GCSFolderType.h @@ -45,10 +45,10 @@ @interface GCSFolderType : NSObject { - NSString *blobTablePattern; // eg 'SOGo_$folderId$_blob - NSString *quickTablePattern; // eg 'SOGo_$folderId$_quick - NSArray *fields; // GCSFieldInfo objects - EOQualifier *folderQualifier; // to further limit the table set + NSString *blobTablePattern; // eg 'SOGo_$folderId$_blob + NSString *quickTablePattern; // eg 'SOGo_$folderId$_quick + NSArray *fields, *quickFields; // GCSFieldInfo objects + EOQualifier *folderQualifier; // to further limit the table set NSString *extractorClassName; GCSFieldExtractor *extractor; } @@ -76,6 +76,7 @@ + (NGResourceLocator *)resourceLocator; - (NSArray *) fields; +- (NSArray *) quickFields; @end #endif /* __GDLContentStore_GCSFolderType_H__ */ diff --git a/SOPE/GDLContentStore/GCSFolderType.m b/SOPE/GDLContentStore/GCSFolderType.m index 8f51794fb..da051c7a3 100644 --- a/SOPE/GDLContentStore/GCSFolderType.m +++ b/SOPE/GDLContentStore/GCSFolderType.m @@ -78,6 +78,8 @@ fields = [[GCSFieldInfo fieldsForPropertyList: [plist objectForKey:@"fields"]] retain]; + quickFields = [[GCSFieldInfo fieldsForPropertyList: + [plist objectForKey:@"quickFields"]] retain]; } return self; @@ -119,6 +121,7 @@ [blobTablePattern release]; [quickTablePattern release]; [fields release]; + [quickFields release]; [folderQualifier release]; [super dealloc]; } @@ -159,11 +162,11 @@ unsigned i, count; sql = [NSMutableString stringWithFormat: @"CREATE TABLE %@ (", _tabName]; - count = [fields count]; + count = [quickFields count]; for (i = 0; i < count; i++) { if (i > 0) [sql appendString:@", "]; - [sql appendFormat: @" %@", [[fields objectAtIndex:i] sqlCreateSection]]; + [sql appendFormat: @" %@", [[quickFields objectAtIndex:i] sqlCreateSection]]; } [sql appendString:@"\n)"]; @@ -200,6 +203,11 @@ return quickExtractor; } +- (NSArray *) quickFields +{ + return quickFields; +} + - (NSArray *) fields { return fields; @@ -217,6 +225,7 @@ [ms appendFormat:@" blobtable='%@'", blobTablePattern]; [ms appendFormat:@" quicktable='%@'", quickTablePattern]; [ms appendFormat:@" fields=%@", fields]; + [ms appendFormat:@" quickFields=%@", fields]; [ms appendFormat:@" extractor=%@", extractorClassName]; if (folderQualifier)