(core) new database structure options to make SOGo use a total of nine tables

pull/203/head
Ludovic Marcotte 2016-03-10 16:34:06 -05:00
parent 819851bb92
commit 4ac41dace7
25 changed files with 1055 additions and 118 deletions

View File

@ -111,6 +111,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoMailObject+ActiveSync.h"
#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h>
#include <unistd.h>
@ -3323,6 +3324,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NSString *tableName, *query;
GCSSpecialQueries *queries;
if ([GCSFolderManager singleStoreMode])
return;
[self folderTableURL];
cm = [GCSChannelManager defaultChannelManager];

View File

@ -1388,6 +1388,32 @@ _SOGoEnableEMailAlarms_ is set to `YES`. For PostgreSQL, the database
URL could be set to something like:
`postgresql://sogo:sogo@localhost:5432/sogo/sogo_alarms_folder`
|S |OCSStoreURL
|Parameter used to set the database URL so that SOGo can use to start
all content data. You must also set `OCSAclURL` and `OCSCacheFolderURL`
if you set this parameter. Using these parameters will allow SOGo to use
a total of nine database tables - and prevent SOGo from creating three
database tables per collection.
For PostgresSQL, set the database URL to something like:
`postgresql://sogo:@localhost:5432/sogo/sogo_store`.
|S |OCSAclURL
|Parameter used to set the database URL so that SOGo can use to start
all ACL data. You must also set `OCSStoreURL` and `OCSCacheFolderURL`
if you set this parameter.
For PostgresSQL, set the database URL to something like:
`postgresql://sogo:@localhost:5432/sogo/sogo_acl`.
|S |OCSCacheFolderURL
|Parameter used to set the database URL so that SOGo can use to start
all cache data. You must also set `OCSStoreURL` and `OCSAclURL`
if you set this parameter.
For PostgresSQL, set the database URL to something like:
`postgresql://sogo:@localhost:5432/sogo/sogo_cache_folder`.
See the "EMail reminders" section in this document for more information.
|=======================================================================

View File

@ -1,6 +1,5 @@
/*
Copyright (C) 2005-2010 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2005-2016 Inverse inc.
This file is part of SOGo.
@ -27,7 +26,6 @@
@class NSArray;
@class NSDictionary;
@class NSMutableDictionary;
@class SOGoCache;

View File

@ -1,6 +1,5 @@
/*
Copyright (C) 2005-2014 Inverse inc.
Copyright (C) 2004-2005 SKYRIX Software AG
Copyright (C) 2005-2016 Inverse inc.
This file is part of SOGo
@ -24,6 +23,7 @@
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <GDLContentStore/GCSFolderType.h>
#import <GDLContentStore/GCSAlarmsFolder.h>
#import <GDLContentStore/GCSSessionsFolder.h>
@ -211,36 +211,94 @@ static BOOL debugLeaks;
[cm releaseChannel: tc];
}
- (void) _checkQuickTableWithTypeName: typeName
withCm: (GCSChannelManager *) cm
tableURL: (NSString *) url
{
GCSFolderType *type;
NSString *sql;
NSString *tableName;
EOAdaptorChannel *channel;
channel = [cm acquireOpenChannelForURL: [NSURL URLWithString: url]];
tableName = [NSString stringWithFormat: @"sogo_quick_%@", typeName];
sql = [NSString stringWithFormat: @"SELECT count(*) FROM %@",
tableName];
if ([channel evaluateExpressionX: sql])
{
type = [GCSFolderType folderTypeWithName: typeName];
if (type)
{
sql = [type sqlQuickCreateWithTableName: tableName];
if (![channel evaluateExpressionX: sql])
[self logWithFormat: @"sogo quick table %@ successfully created!",
tableName];
}
}
else
[channel cancelFetch];
[cm releaseChannel:channel];
}
//
// If OCSStoreURL is defined, we also check for OCSAclURL, OCSCacheFolderURL
// and we create the combined quick tables.
//
- (BOOL) _checkMandatoryTables
{
GCSChannelManager *cm;
GCSFolderManager *fm;
NSString *urlStrings[] = {@"SOGoProfileURL", @"OCSFolderInfoURL", nil};
NSString **urlString;
NSString *value;
NSArray *urlStrings;
NSArray *quickTypeStrings;
NSString *tmp, *value;
SOGoSystemDefaults *defaults;
BOOL ok;
NSEnumerator *e;
BOOL ok, combined;
defaults = [SOGoSystemDefaults sharedSystemDefaults];
ok = YES;
if ([GCSFolderManager singleStoreMode])
{
urlStrings = [NSArray arrayWithObjects: @"SOGoProfileURL", @"OCSFolderInfoURL", @"OCSStoreURL", @"OCSAclURL", @"OCSCacheFolderURL", nil];
quickTypeStrings = [NSArray arrayWithObjects: @"contact", @"appointment", nil];
combined = YES;
}
else
{
urlStrings = [NSArray arrayWithObjects: @"SOGoProfileURL", @"OCSFolderInfoURL", nil];
combined = NO;
}
cm = [GCSChannelManager defaultChannelManager];
urlString = urlStrings;
while (ok && *urlString)
e = [urlStrings objectEnumerator];
while (ok && (tmp = [e nextObject]))
{
value = [defaults stringForKey: *urlString];
value = [defaults stringForKey: tmp];
if (value)
{
[self _checkTableWithCM: cm tableURL: value andType: *urlString];
urlString++;
}
[self _checkTableWithCM: cm tableURL: value andType: tmp];
else
{
[self errorWithFormat: @"No value specified for '%@'", *urlString];
[self errorWithFormat: @"No value specified for '%@'", tmp];
ok = NO;
}
}
if (combined)
{
e = [quickTypeStrings objectEnumerator];
while ((tmp = [e nextObject]))
{
[self _checkQuickTableWithTypeName: tmp
withCm: cm
tableURL: [defaults stringForKey: @"OCSFolderInfoURL"]];
}
}
if (ok)
{
fm = [GCSFolderManager defaultFolderManager];

3
NEWS
View File

@ -1,6 +1,9 @@
3.0.3 (2016-03-dd)
------------------
New features
- [core] new database structure options to make SOGo use a total of nine tables
Enhancements
- [web] updated Angular Material to version 1.0.6

View File

@ -1,8 +1,6 @@
/* MAPIStoreUserContext.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2012-2016 Inverse inc
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -35,6 +33,7 @@
#import <NGImap4/NGImap4Connection.h>
#import <GDLContentStore/GCSChannelManager.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <SOGo/SOGoDomainDefaults.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserFolder.h>
@ -339,6 +338,9 @@ static NSMapTable *contextsTable = nil;
NSString *tableName, *query;
GCSSpecialQueries *queries;
if ([GCSFolderManager singleStoreMode])
return;
[self folderTableURL];
cm = [GCSChannelManager defaultChannelManager];

View File

@ -91,13 +91,6 @@ static GCSStringFormatter *stringFormatter = nil;
NSEnumerator *fields;
GCSFieldInfo *field;
NSString *fieldName;
if (![_loc isNotNull])
{
[self errorWithFormat:@"missing quicktable parameter!"];
[self release];
return nil;
}
if ((self = [super init])) {
folderManager = [_fm retain];
@ -190,12 +183,31 @@ static GCSStringFormatter *stringFormatter = nil;
}
- (NSURL *)location {
if ([GCSFolderManager singleStoreMode])
return [folderManager storeLocation];
return location;
}
- (NSURL *)quickLocation {
if ([GCSFolderManager singleStoreMode])
{
NSString *baseURL;
NSRange range;
baseURL = [[folderManager folderInfoLocation] absoluteString];
range = [baseURL rangeOfString: @"/" options: NSBackwardsSearch];
if (range.location != NSNotFound)
baseURL = [baseURL substringToIndex: range.location];
return [NSURL URLWithString: [NSString stringWithFormat: @"%@/%@", baseURL, [self quickTableName]]];
}
return quickLocation;
}
- (NSURL *)aclLocation {
if ([GCSFolderManager singleStoreMode])
return [folderManager aclLocation];
return aclLocation;
}
@ -211,6 +223,9 @@ static GCSStringFormatter *stringFormatter = nil;
return [[self location] gcsTableName];
}
- (NSString *)quickTableName {
if ([GCSFolderManager singleStoreMode])
return [NSString stringWithFormat: @"sogo_quick_%@", [folderTypeName lowercaseString]];
return [[self quickLocation] gcsTableName];
}
- (NSString *)aclTableName {
@ -473,6 +488,16 @@ static GCSStringFormatter *stringFormatter = nil;
}
whereSql = [NSMutableArray array];
if ([GCSFolderManager singleStoreMode])
{
if (requirement == bothTableRequired)
[whereSql addObject: [NSString stringWithFormat:
@"(a.c_folder_id = %@ AND b.c_folder_id = %@)",
folderId, folderId]];
else
[whereSql addObject: [NSString stringWithFormat: @"c_folder_id = %@",
folderId]];
}
if (qualifier)
{
whereString = [NSString stringWithFormat: @"(%@)",
@ -693,6 +718,8 @@ andAttribute: (EOAttribute *)_attribute
[sql appendString:@"INSERT INTO "];
[sql appendString:_table];
[sql appendString:@" ("];
if ([GCSFolderManager singleStoreMode])
[sql appendString:@"c_folder_id, "];
for (i = 0, count = [keys count]; i < count; i++) {
if (i != 0) [sql appendString:@", "];
@ -700,6 +727,8 @@ andAttribute: (EOAttribute *)_attribute
}
[sql appendString:@") VALUES ("];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat:@"%@, ", folderId];
for (i = 0, count = [keys count]; i < count; i++) {
fieldName = [keys objectAtIndex:i];
@ -767,6 +796,8 @@ andAttribute: (EOAttribute *)_attribute
}
[sql appendString:@" WHERE "];
if ([GCSFolderManager singleStoreMode])
[sql appendString: [NSString stringWithFormat: @"c_folder_id = %@ AND ", folderId]];
[sql appendString:_colname];
[sql appendString:@" = "];
attribute = [self _attributeForColumn: _colname];
@ -853,22 +884,39 @@ andAttribute: (EOAttribute *)_attribute
attribute1 = [self _attributeForColumn: _colname];
if (_colname2 == nil)
{
qualifier = [[EOSQLQualifier alloc] initWithEntity: _entity
qualifierFormat: @"%A = %@", _colname,
[self _formatRowValue:_value
withAdaptor: _adaptor andAttribute: attribute1]];
if ([GCSFolderManager singleStoreMode])
qualifier = [[EOSQLQualifier alloc] initWithEntity: _entity
qualifierFormat: @"%A = %@ AND c_folder_id = %@", _colname,
[self _formatRowValue:_value
withAdaptor: _adaptor andAttribute: attribute1], folderId];
else
qualifier = [[EOSQLQualifier alloc] initWithEntity: _entity
qualifierFormat: @"%A = %@", _colname,
[self _formatRowValue:_value
withAdaptor: _adaptor andAttribute: attribute1]];
}
else
{
attribute2 = [self _attributeForColumn: _colname2];
qualifier = [[EOSQLQualifier alloc] initWithEntity: _entity
qualifierFormat: @"%A = %@ AND %A = %@",
_colname,
[self _formatRowValue:_value
withAdaptor: _adaptor andAttribute: attribute1],
_colname2,
[self _formatRowValue:_value2
withAdaptor: _adaptor andAttribute: attribute2]];
if ([GCSFolderManager singleStoreMode])
qualifier = [[EOSQLQualifier alloc] initWithEntity: _entity
qualifierFormat: @"%A = %@ AND %A = %@ AND c_folder_id = %@",
_colname,
[self _formatRowValue:_value
withAdaptor: _adaptor andAttribute: attribute1],
_colname2,
[self _formatRowValue:_value2
withAdaptor: _adaptor andAttribute: attribute2]];
else
qualifier = [[EOSQLQualifier alloc] initWithEntity: _entity
qualifierFormat: @"%A = %@ AND %A = %@",
_colname,
[self _formatRowValue:_value
withAdaptor: _adaptor andAttribute: attribute1],
_colname2,
[self _formatRowValue:_value2
withAdaptor: _adaptor andAttribute: attribute2],
folderId];
}
return AUTORELEASE(qualifier);
@ -887,10 +935,17 @@ andAttribute: (EOAttribute *)_attribute
table = [self storeTableName];
attribute = [self _attributeForColumn: @"c_name"];
delSql = [NSString stringWithFormat: @"DELETE FROM %@"
@" WHERE c_name = %@", table,
[self _formatRowValue: recordName
withAdaptor: [adaptorCtx adaptor]
if ([GCSFolderManager singleStoreMode])
delSql = [NSString stringWithFormat: @"DELETE FROM %@"
@" WHERE c_name = %@ AND c_folder_id = %@", table,
[self _formatRowValue: recordName
withAdaptor: [adaptorCtx adaptor]
andAttribute: attribute], folderId];
else
delSql = [NSString stringWithFormat: @"DELETE FROM %@"
@" WHERE c_name = %@", table,
[self _formatRowValue: recordName
withAdaptor: [adaptorCtx adaptor]
andAttribute: attribute]];
[channel evaluateExpressionX: delSql];
@ -1170,6 +1225,8 @@ andAttribute: (EOAttribute *)_attribute
delsql = [delsql stringByAppendingString: [self _formatRowValue:_name
withAdaptor: [adaptorCtx adaptor]
andAttribute: [self _attributeForColumn: @"c_name"]]];
if ([GCSFolderManager singleStoreMode])
delsql = [delsql stringByAppendingFormat:@" AND c_folder_id = %@", folderId];
if ((error = [storeChannel evaluateExpressionX:delsql]) != nil) {
[self errorWithFormat:
@"%s: cannot delete content '%@': %@",
@ -1182,6 +1239,8 @@ andAttribute: (EOAttribute *)_attribute
delsql = [delsql stringByAppendingString: [self _formatRowValue:_name
withAdaptor: [adaptorCtx adaptor]
andAttribute: [self _attributeForColumn: @"c_name"]]];
if ([GCSFolderManager singleStoreMode])
delsql = [delsql stringByAppendingFormat:@" AND c_folder_id = %@", folderId];
if ((error = [quickChannel evaluateExpressionX:delsql]) != nil) {
[self errorWithFormat:
@"%s: cannot delete quick row '%@': %@",
@ -1229,18 +1288,24 @@ andAttribute: (EOAttribute *)_attribute
if (!ofFlags.sameTableForQuick) [[quickChannel adaptorContext] beginTransaction];
[[storeChannel adaptorContext] beginTransaction];
query = [NSString stringWithFormat: @"DELETE FROM %@", [self storeTableName]];
if ([GCSFolderManager singleStoreMode])
query = [NSString stringWithFormat: @"DELETE FROM %@ WHERE c_folder_id = %@", [self storeTableName], folderId];
else
query = [NSString stringWithFormat: @"DELETE FROM %@", [self storeTableName]];
error = [storeChannel evaluateExpressionX:query];
if (error)
[self errorWithFormat: @"%s: cannot delete content '%@': %@",
__PRETTY_FUNCTION__, query, error];
else if (!ofFlags.sameTableForQuick) {
/* content row deleted, now delete the quick row */
/* content row deleted, now delete the quick row */
if ([GCSFolderManager singleStoreMode])
query = [NSString stringWithFormat: @"DELETE FROM %@ WHERE c_folder_id = %@", [self quickTableName], folderId];
else
query = [NSString stringWithFormat: @"DELETE FROM %@", [self quickTableName]];
error = [quickChannel evaluateExpressionX: query];
if (error)
[self errorWithFormat: @"%s: cannot delete quick row '%@': %@",
__PRETTY_FUNCTION__, query, error];
error = [quickChannel evaluateExpressionX: query];
if (error)
[self errorWithFormat: @"%s: cannot delete quick row '%@': %@",
__PRETTY_FUNCTION__, query, error];
}
/* release channels and return */
@ -1271,17 +1336,26 @@ andAttribute: (EOAttribute *)_attribute
[[channel adaptorContext] beginTransaction];
table = [self storeTableName];
if ([table length] > 0) {
delsql = [@"DROP TABLE " stringByAppendingString: table];
if ([GCSFolderManager singleStoreMode])
delsql = [NSString stringWithFormat: @"DELETE FROM %@ WHERE c_folder_id = %@", table, folderId];
else
delsql = [@"DROP TABLE " stringByAppendingString: table];
[channel evaluateExpressionX:delsql];
}
table = [self quickTableName];
if ([table length] > 0) {
delsql = [@"DROP TABLE " stringByAppendingString: table];
if ([GCSFolderManager singleStoreMode])
delsql = [NSString stringWithFormat: @"DELETE FROM %@ WHERE c_folder_id = %@", table, folderId];
else
delsql = [@"DROP TABLE " stringByAppendingString: table];
[channel evaluateExpressionX:delsql];
}
table = [self aclTableName];
if ([table length] > 0) {
delsql = [@"DROP TABLE " stringByAppendingString: table];
if ([GCSFolderManager singleStoreMode])
delsql = [NSString stringWithFormat: @"DELETE FROM %@ WHERE c_folder_id = %@", table, folderId];
else
delsql = [@"DROP TABLE " stringByAppendingString: table];
[channel evaluateExpressionX:delsql];
}
@ -1376,10 +1450,17 @@ andAttribute: (EOAttribute *)_attribute
[sql appendString:@"SELECT c_uid, c_object, c_role"];
[sql appendString:@" FROM "];
[sql appendString:[self aclTableName]];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat:@" WHERE c_folder_id = %@", folderId];
if (qualifier != nil) {
[sql appendString:@" WHERE "];
[sql appendString:[self _sqlForQualifier:qualifier]];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat:@" AND (%@)", [self _sqlForQualifier:qualifier]];
else
{
[sql appendString:@" WHERE "];
[sql appendString:[self _sqlForQualifier:qualifier]];
}
}
if ([sortOrderings count] > 0) {
[sql appendString:@" ORDER BY "];
@ -1462,10 +1543,14 @@ andAttribute: (EOAttribute *)_attribute
[sql appendString:[self aclTableName]];
qSql = [self _sqlForQualifier: [_fs qualifier]];
if (qSql)
[sql appendFormat:@" WHERE %@", qSql];
/* open channel */
{
if ([GCSFolderManager singleStoreMode])
[sql appendFormat:@" WHERE c_folder_id = %@ AND (%@)", folderId, qSql];
else
[sql appendFormat:@" WHERE %@", qSql];
}
/* open channel */
if ((channel = [self acquireAclChannel]) == nil) {
[self errorWithFormat:@"could not open acl channel!"];
return;
@ -1495,11 +1580,21 @@ andAttribute: (EOAttribute *)_attribute
count = 0;
sqlString = [NSMutableString stringWithFormat:
@"SELECT COUNT(*) AS CNT FROM %@",
[self storeTableName]];
if ([GCSFolderManager singleStoreMode])
sqlString = [NSMutableString stringWithFormat:
@"SELECT COUNT(*) AS CNT FROM %@ WHERE c_folder_id = %@",
[self storeTableName], folderId];
else
sqlString = [NSMutableString stringWithFormat:
@"SELECT COUNT(*) AS CNT FROM %@",
[self storeTableName]];
if (excludeDeleted)
[sqlString appendString: @" WHERE (c_deleted != 1 OR c_deleted IS NULL)"];
{
if ([GCSFolderManager singleStoreMode])
[sqlString appendString: @" AND (c_deleted != 1 OR c_deleted IS NULL)"];
else
[sqlString appendString: @" WHERE (c_deleted != 1 OR c_deleted IS NULL)"];
}
channel = [self acquireStoreChannel];
if (channel)

View File

@ -38,15 +38,28 @@
GCSChannelManager *channelManager;
NSDictionary *nameToType;
NSURL *folderInfoLocation;
NSURL *storeLocation;
NSURL *aclLocation;
NSURL *cacheFolderLocation;
}
+ (BOOL) singleStoreMode;
+ (id)defaultFolderManager;
- (id)initWithFolderInfoLocation:(NSURL *)_url;
- (id)initWithFolderInfoLocation: (NSURL *)_infoUrl
andStoreLocation: (NSURL *)_storeUrl
andAclLocation: (NSURL *)_aclUrl
andCacheFolderLocation: (NSURL *)_cacheFolderUrl;
/* accessors */
- (NSURL *)folderInfoLocation;
- (NSString *)folderInfoTableName;
- (NSURL *)storeLocation;
- (NSString *)storeTableName;
- (NSURL *)aclLocation;
- (NSString *)aclTableName;
- (NSURL *)cacheFolderLocation;
- (NSString *)cacheFolderTableName;
/* connection */

View File

@ -25,6 +25,7 @@
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSURL.h>
#import <Foundation/NSUserDefaults.h>
#import <NGExtensions/NSNull+misc.h>
@ -74,6 +75,7 @@ static NSString *GCSPathRecordName = @"c_path";
static NSString *GCSGenericFolderTypeName = @"Container";
static const char *GCSPathColumnPattern = "c_path%i";
static NSCharacterSet *asciiAlphaNumericCS = nil;
static BOOL _singleStoreMode = NO;
+ (void) initialize
{
@ -96,11 +98,24 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
@"abcdefghijklmnopqrstuvwxyz"];
[asciiAlphaNumericCS retain];
}
if ([ud stringForKey: @"OCSStoreURL"] &&
[ud stringForKey: @"OCSAclURL"] &&
[ud stringForKey: @"OCSCacheFolderURL"])
_singleStoreMode = YES;
}
+ (BOOL) singleStoreMode
{
return _singleStoreMode;
}
+ (id)defaultFolderManager {
NSString *s;
NSURL *url;
NSURL *infoUrl;
NSURL *storeUrl;
NSURL *aclUrl;
NSURL *cacheFolderUrl;
if (!fm)
{
@ -110,18 +125,66 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
__PRETTY_FUNCTION__);
return nil;
}
if ((url = [NSURL URLWithString:s]) == nil) {
if ((infoUrl = [NSURL URLWithString:s]) == nil) {
NSLog(@"ERROR(%s): default 'OCSFolderInfoURL' is not a valid URL: '%@'",
__PRETTY_FUNCTION__, s);
return nil;
}
if ((fm = [[self alloc] initWithFolderInfoLocation:url]) == nil) {
NSLog(@"ERROR(%s): could not create folder manager with URL: '%@'",
__PRETTY_FUNCTION__, [url absoluteString]);
if (_singleStoreMode)
{
s = [[NSUserDefaults standardUserDefaults] stringForKey:@"OCSStoreURL"];
if ([s length] == 0) {
NSLog(@"ERROR(%s): default 'OCSStoreURL' is not configured.",
__PRETTY_FUNCTION__);
return nil;
}
if ((storeUrl = [NSURL URLWithString:s]) == nil) {
NSLog(@"ERROR(%s): default 'OCSStoreURL' is not a valid URL: '%@'",
__PRETTY_FUNCTION__, s);
return nil;
}
s = [[NSUserDefaults standardUserDefaults] stringForKey:@"OCSAclURL"];
if ([s length] == 0) {
NSLog(@"ERROR(%s): default 'OCSAclURL' is not configured.",
__PRETTY_FUNCTION__);
return nil;
}
if ((aclUrl = [NSURL URLWithString:s]) == nil) {
NSLog(@"ERROR(%s): default 'OCSAclURL' is not a valid URL: '%@'",
__PRETTY_FUNCTION__, s);
return nil;
}
s = [[NSUserDefaults standardUserDefaults] stringForKey:@"OCSCacheFolderURL"];
if ([s length] == 0) {
NSLog(@"ERROR(%s): default 'OCSCacheFolderURL' is not configured.",
__PRETTY_FUNCTION__);
return nil;
}
if ((cacheFolderUrl = [NSURL URLWithString:s]) == nil) {
NSLog(@"ERROR(%s): default 'OCSCacheFolderURL' is not a valid URL: '%@'",
__PRETTY_FUNCTION__, s);
return nil;
}
}
else
{
storeUrl = nil;
aclUrl = nil;
cacheFolderUrl = nil;
}
if ((fm = [[self alloc] initWithFolderInfoLocation: infoUrl
andStoreLocation: storeUrl
andAclLocation: aclUrl
andCacheFolderLocation: cacheFolderUrl]) == nil) {
NSLog(@"ERROR(%s): could not create folder manager with URLs: '%@', '%@', '%@'",
__PRETTY_FUNCTION__, [infoUrl absoluteString],
[storeUrl absoluteString], [aclUrl absoluteString]);
return nil;
}
if (debugOn)
[self debugWithFormat:@"Note: setup default manager at: %@", url];
[self debugWithFormat:@"Note: setup default manager at: %@", infoUrl];
}
return fm;
@ -159,20 +222,81 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
return typeMap;
}
- (id)initWithFolderInfoLocation:(NSURL *)_url {
if (_url == nil) {
- (id)initWithFolderInfoLocation: (NSURL *)_infoUrl
andStoreLocation: (NSURL *)_storeUrl
andAclLocation: (NSURL *)_aclUrl
andCacheFolderLocation: (NSURL *)_cacheFolderUrl {
if (_infoUrl == nil) {
[self logWithFormat:@"ERROR(%s): missing folder info url!",
__PRETTY_FUNCTION__];
[self release];
return nil;
}
if (_singleStoreMode)
{
if (_storeUrl == nil) {
[self logWithFormat:@"ERROR(%s): missing folder store url!",
__PRETTY_FUNCTION__];
[self release];
return nil;
}
if (_aclUrl == nil) {
[self logWithFormat:@"ERROR(%s): missing folder acl url!",
__PRETTY_FUNCTION__];
[self release];
return nil;
}
if (_cacheFolderUrl == nil) {
[self logWithFormat:@"ERROR(%s): missing cache folder url!",
__PRETTY_FUNCTION__];
[self release];
return nil;
}
}
if ((self = [super init])) {
channelManager = [[GCSChannelManager defaultChannelManager] retain];
folderInfoLocation = [_url retain];
folderInfoLocation = [_infoUrl retain];
if (_singleStoreMode)
{
storeLocation = [_storeUrl retain];
aclLocation = [_aclUrl retain];
cacheFolderLocation = [_cacheFolderUrl retain];
}
else
{
storeLocation = nil;
aclLocation = nil;
cacheFolderLocation = nil;
}
if ([[self folderInfoTableName] length] == 0) {
[self logWithFormat:@"ERROR(%s): missing tablename in URL: %@",
__PRETTY_FUNCTION__, [_url absoluteString]];
[self logWithFormat:@"ERROR(%s): missing tablename in URL: %@",
__PRETTY_FUNCTION__, [_infoUrl absoluteString]];
[self release];
return nil;
}
if (_singleStoreMode && [[self storeTableName] length] == 0) {
[self logWithFormat:@"ERROR(%s): missing tablename in URL: %@",
__PRETTY_FUNCTION__, [_storeUrl absoluteString]];
[self release];
return nil;
}
if (_singleStoreMode && [[self aclTableName] length] == 0) {
[self logWithFormat:@"ERROR(%s): missing tablename in URL: %@",
__PRETTY_FUNCTION__, [_aclUrl absoluteString]];
[self release];
return nil;
}
if (_singleStoreMode && [[self cacheFolderTableName] length] == 0) {
[self logWithFormat:@"ERROR(%s): missing tablename in URL: %@",
__PRETTY_FUNCTION__, [_cacheFolderUrl absoluteString]];
[self release];
return nil;
}
@ -201,6 +325,31 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
return [[self folderInfoLocation] gcsTableName];
}
- (NSURL *)storeLocation {
return storeLocation;
}
- (NSString *)storeTableName {
return [[self storeLocation] gcsTableName];
}
- (NSURL *)aclLocation {
return aclLocation;
}
- (NSString *)aclTableName {
return [[self aclLocation] gcsTableName];
}
- (NSURL *)cacheFolderLocation {
return cacheFolderLocation;
}
- (NSString *)cacheFolderTableName {
return [[self cacheFolderLocation] gcsTableName];
}
/* connection */
- (GCSChannelManager *)channelManager {
@ -266,7 +415,7 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
GCSFolderType *folderType;
NSString *folderTypeName, *locationString, *folderName, *path;
NSNumber *folderId;
NSURL *location, *quickLocation, *aclLocation;
NSURL *location, *quickLocation, *acl_location;
if (_record == nil) return nil;
@ -309,7 +458,7 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
}
locationString = [_record objectForKey:@"c_acl_location"];
aclLocation = [locationString isNotNull]
acl_location = [locationString isNotNull]
? [NSURL URLWithString:locationString]
: nil;
@ -317,7 +466,7 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
folderTypeName:folderTypeName
folderType:folderType
location:location quickLocation:quickLocation
aclLocation:aclLocation
aclLocation:acl_location
folderManager:self];
return [folder autorelease];
}
@ -766,7 +915,7 @@ static NSCharacterSet *asciiAlphaNumericCS = nil;
baseURL, aclTableName,
folderType];
error = [channel evaluateExpressionX: sql];
if (!error)
if (!_singleStoreMode && !error)
{
specialQuery = [channel specialQueries];
createQuery = [specialQuery createFolderTableWithName: tableName];

View File

@ -31,6 +31,7 @@
#import <NGExtensions/NGResourceLocator.h>
#import "GCSFolderManager.h"
#import "GCSFolderType.h"
#import "GCSFolder.h"
#import "GCSFieldInfo.h"
@ -157,15 +158,52 @@
{
NSMutableString *sql;
unsigned i, count;
GCSFieldInfo *field;
BOOL combined;
combined = NO;
if ([GCSFolderManager singleStoreMode])
combined = YES;
sql = [NSMutableString stringWithFormat: @"CREATE TABLE %@ (", _tabName];
if (combined)
[sql appendString: @"c_folder_id INT NOT NULL, "];
count = [quickFields count];
for (i = 0; i < count; i++)
{
if (i > 0) [sql appendString:@", "];
[sql appendFormat: @" %@", [[quickFields objectAtIndex:i] sqlCreateSection]];
field = [quickFields objectAtIndex:i];
if (i != 0) [sql appendString: @", "];
[sql appendString:[field columnName]];
[sql appendString:@" "];
[sql appendString:[field sqlType]];
[sql appendString:@" "];
if (![field doesAllowNull]) [sql appendString:@"NOT "];
[sql appendString:@"NULL"];
if (!combined && [field isPrimaryKey])
[sql appendString:@" PRIMARY KEY"];
}
[sql appendString:@"\n)"];
// Define primary key constraint for c_folder_id and additional primary key fields
if (combined)
{
[sql appendFormat:@", CONSTRAINT %@_pkey PRIMARY KEY(c_folder_id", _tabName];
for (i = 0; i < count; i++)
{
field = [quickFields objectAtIndex:i];
if ([field isPrimaryKey])
[sql appendFormat:@", %@", [field columnName]];
}
[sql appendString:@")"];
}
[sql appendString:@")"];
return sql;
}

View File

@ -0,0 +1,200 @@
#!/bin/bash
STOREFIELDS="c_name, c_content, c_creationdate, c_lastmodified, c_version, c_deleted"
APPOINTMENTFIELDS="c_name, c_uid, c_startdate, c_enddate, c_cycleenddate, c_title, c_participants, c_isallday, c_iscycle, c_cycleinfo, \
c_classification, c_isopaque, c_status, c_priority, c_location, c_orgmail, c_partmails, c_partstates, c_category, c_sequence, c_component, c_nextalarm, c_description"
CONTACTFIELDS="c_name, c_givenname, c_cn, c_sn, c_screenname, c_l, c_mail, c_o, c_ou, c_telephonenumber, c_categories, c_component"
IFS=" "
# Parse postgres connection string from OCSFolderInfoURL in sogo.conf
set $(sogo-tool dump-defaults -f /etc/sogo/sogo.conf | awk -F\" '/ OCSFolderInfoURL =/ {print $2}' \
| sed -n 's/\([^:]\+\):\/\/\([^:]\+\):\([^@]\+\)@\([^:]\+\):\([^/]\+\)\/\([^/]\+\)\/\([^/]\+\)/\1 \2 \3 \4 \5 \6 \7/p')
PROTOCOL=$1
USER=$2
PWD=$3
HOST=$4
PORT=$5
DB=$6
TABLE=$7
if [ -z "$PROTOCOL" ] || [ -z "$USER" ] || [ -z "$HOST" ] || [ -z "$PORT" ] || [ -z "$DB" ] || [ -z "$TABLE" ]; then
echo "ERROR: Failed to parse value of OCSFolderInfoURL in /etc/sogo/sogo.conf" 1>&2
exit 1
fi
if ! [ "$PROTOCOL" = "mysql" ]; then
echo "ERROR: Unsupported protocol $PROTOCOL. Use this script for migrating mysql databases." 1>&2
exit 1
fi
# Create temporary files
OPTSFILE=$(mktemp)
TABLEFILE=$(mktemp)
SQLFILE=$(mktemp)
trap "rm -rf $TABLEFILE $OPTSFILE $SQLFILE" EXIT
# Save password for subsequent batch-mode calls of mysql
cat > $OPTSFILE <<HERE
[client]
password="$PWD"
HERE
#########################
# Create new tables
# Check if table sogo_store exists
CHECK=$(mysql --defaults-file="$OPTSFILE" -u $USER -h $HOST -P $PORT $DB -B -N -e \
"SELECT TRUE FROM information_schema.tables WHERE table_name='sogo_store'")
RET=$?
if [ $RET -ne 0 ]; then
echo "ERROR: mysql return error $RET" 1>&2
exit 1
fi
if ! [ "$CHECK" = "1" ]; then
cat >> $SQLFILE <<HERE
ALTER TABLE $TABLE MODIFY COLUMN c_location integer NULL;
CREATE TABLE sogo_store
(
c_folder_id integer NOT NULL,
c_name character varying(255) NOT NULL,
c_content mediumtext NOT NULL,
c_creationdate integer NOT NULL,
c_lastmodified integer NOT NULL,
c_version integer NOT NULL,
c_deleted integer,
CONSTRAINT sogo_store_pkey PRIMARY KEY (c_folder_id, c_name)
);
CREATE TABLE sogo_acl
(
c_folder_id integer NOT NULL,
c_object character varying(255) NOT NULL,
c_uid character varying(255) NOT NULL,
c_role character varying(80) NOT NULL
);
CREATE INDEX sogo_acl_c_folder_id_idx ON sogo_acl(c_folder_id);
CREATE INDEX sogo_acl_c_uid_idx ON sogo_acl(c_uid);
CREATE TABLE sogo_quick_appointment
(
c_folder_id integer NOT NULL,
c_name character varying(255) NOT NULL,
c_uid character varying(255) NOT NULL,
c_startdate integer,
c_enddate integer,
c_cycleenddate integer,
c_title character varying(1000) NOT NULL,
c_participants text,
c_isallday integer,
c_iscycle integer,
c_cycleinfo text,
c_classification integer NOT NULL,
c_isopaque integer NOT NULL,
c_status integer NOT NULL,
c_priority integer,
c_location character varying(255),
c_orgmail character varying(255),
c_partmails text,
c_partstates text,
c_category character varying(255),
c_sequence integer,
c_component character varying(10) NOT NULL,
c_nextalarm integer,
c_description text,
CONSTRAINT sogo_quick_appointment_pkey PRIMARY KEY (c_folder_id, c_name)
);
CREATE TABLE sogo_quick_contact
(
c_folder_id integer NOT NULL,
c_name character varying(255) NOT NULL,
c_givenname character varying(255),
c_cn character varying(255),
c_sn character varying(255),
c_screenname character varying(255),
c_l character varying(255),
c_mail character varying(255),
c_o character varying(255),
c_ou character varying(255),
c_telephonenumber character varying(255),
c_categories character varying(255),
c_component character varying(10) NOT NULL,
CONSTRAINT sogo_quick_contact_pkey PRIMARY KEY (c_folder_id, c_name)
);
HERE
fi
#########################
# Merge per-folder tables
# Retrieve folder infos
mysql --defaults-file="$OPTSFILE" -u $USER -h $HOST -P $PORT $DB -B -N -e "SELECT c_path, c_folder_id, c_folder_type, SUBSTRING_INDEX(c_quick_location, '/', -1), \
SUBSTRING_INDEX(c_location, '/', -1), SUBSTRING_INDEX(c_acl_location, '/', -1) FROM $TABLE WHERE c_location IS NOT NULL" > $TABLEFILE
RET=$?
if [ $RET -ne 0 ]; then
echo "ERROR: mysql returned error $RET" 1>&2
exit 1
fi
cat $TABLEFILE | sed "s/[[:space:]]\+/ /g" | while read LINE
do
set $LINE
FOLDERID=$2
FOLDERTYPE=$3
QUICKTABLE=$4
STORETABLE=$5
ACLTABLE=$6
if [ "$FOLDERTYPE" != "Appointment" ] && [ "$FOLDERTYPE" != "Contact" ]; then
echo "ERROR: Unknown folder type $FOLDERTYPE, folder id $FOLDERID" 1>&2
exit 1
fi
# Merge content and acl
echo "INSERT INTO sogo_store(c_folder_id, $STOREFIELDS) SELECT $FOLDERID, $STOREFIELDS FROM $STORETABLE;" >> $SQLFILE
echo "INSERT INTO sogo_acl(c_folder_id, c_object, c_uid, c_role) SELECT $FOLDERID, c_object, c_uid, c_role FROM $ACLTABLE;" >> $SQLFILE
# Merge quick table
if [ "$FOLDERTYPE" = "Appointment" ]; then
echo "INSERT INTO sogo_quick_appointment(c_folder_id, $APPOINTMENTFIELDS) SELECT $FOLDERID, $APPOINTMENTFIELDS FROM $QUICKTABLE;" >> $SQLFILE
else
echo "INSERT INTO sogo_quick_contact(c_folder_id, $CONTACTFIELDS) SELECT $FOLDERID, $CONTACTFIELDS FROM $QUICKTABLE;" >> $SQLFILE
fi
# Drop migrated tables and update folder info
echo "DROP TABLE $QUICKTABLE;" >> $SQLFILE
echo "DROP TABLE $STORETABLE;" >> $SQLFILE
echo "DROP TABLE $ACLTABLE;" >> $SQLFILE
echo "UPDATE sogo_folder_info SET c_location = NULL, c_quick_location = NULL, c_acl_location = NULL WHERE c_folder_id = $FOLDERID;" >> $SQLFILE
echo >> $SQLFILE
done
echo "Merging tables...."
mysql --defaults-file="$OPTSFILE" -u $USER -h $HOST -P $PORT $DB -B -N < $SQLFILE
RET=$?
if [ $RET -ne 0 ]; then
echo "ERROR: mysql returned error $RET" 1>&2
exit 1
fi
#########################
# Patch sogo.conf
if ! (grep -q "OCSStoreURL" /etc/sogo/sogo.conf); then
echo "Patching /etc/sogo/sogo.conf...."
# Generate properties OCSStoreURL and OCSAclURL
sed "s/\(.*\)OCSFolderInfoURL.*$/\0\n\1OCSStoreURL = \"mysql:\/\/$USER:$PASSWORD@$HOST:$PORT\/$DB\/sogo_store\";\
\n\1OCSAclURL = \"mysql:\/\/$USER:$PASSWORD@$HOST:$PORT\/$DB\/sogo_acl\";/g" -i /etc/sogo/sogo.conf
fi

View File

@ -0,0 +1,198 @@
#!/bin/bash
STOREFIELDS="c_name, c_content, c_creationdate, c_lastmodified, c_version, c_deleted"
APPOINTMENTFIELDS="c_name, c_uid, c_startdate, c_enddate, c_cycleenddate, c_title, c_participants, c_isallday, c_iscycle, c_cycleinfo, \
c_classification, c_isopaque, c_status, c_priority, c_location, c_orgmail, c_partmails, c_partstates, c_category, c_sequence, c_component, c_nextalarm, c_description"
CONTACTFIELDS="c_name, c_givenname, c_cn, c_sn, c_screenname, c_l, c_mail, c_o, c_ou, c_telephonenumber, c_categories, c_component"
IFS=" "
# Parse postgres connection string from OCSFolderInfoURL in sogo.conf
set $(sogo-tool dump-defaults -f /etc/sogo/sogo.conf | awk -F\" '/ OCSFolderInfoURL =/ {print $2}' \
| sed -n 's/\([^:]\+\):\/\/\([^:]\+\):\([^@]\+\)@\([^:]\+\):\([^/]\+\)\/\([^/]\+\)\/\([^/]\+\)/\1 \2 \3 \4 \5 \6 \7/p')
PROTOCOL=$1
USER=$2
PWD=$3
HOST=$4
PORT=$5
DB=$6
TABLE=$7
if [ -z "$PROTOCOL" ] || [ -z "$USER" ] || [ -z "$HOST" ] || [ -z "$PORT" ] || [ -z "$DB" ] || [ -z "$TABLE" ]; then
echo "ERROR: Failed to parse value of OCSFolderInfoURL in /etc/sogo/sogo.conf" 1>&2
exit 1
fi
if ! [ "$PROTOCOL" = "postgresql" ]; then
echo "ERROR: Unsupported protocol $PROTOCOL. Use this script for migrating postgresql databases." 1>&2
exit 1
fi
# Create temporary files
export PGPASSFILE=$(mktemp)
TABLEFILE=$(mktemp)
SQLFILE=$(mktemp)
trap "rm -rf $TABLEFILE $PGPASSFILE $SQLFILE" EXIT
# Save password for subsequent batch-mode calls of psql
echo "*:*:*:$USER:$PWD" > $PGPASSFILE
#########################
# Create new tables
# Check if table sogo_store exists
CHECK=$(psql -A -F " " -w -t -U $USER -h $HOST $DB -c "SELECT TRUE FROM information_schema.tables WHERE table_name='sogo_store'")
RET=$?
if [ $RET -ne 0 ]; then
echo "ERROR: postgresql returned error $RET" 1>&2
exit 1
fi
if [ "$CHECK" != "t" ]; then
cat >> $SQLFILE <<HERE
ALTER TABLE $TABLE ALTER COLUMN c_location DROP NOT NULL;
CREATE TABLE sogo_store
(
c_folder_id integer NOT NULL,
c_name character varying(255) NOT NULL,
c_content text NOT NULL,
c_creationdate integer NOT NULL,
c_lastmodified integer NOT NULL,
c_version integer NOT NULL,
c_deleted integer,
CONSTRAINT sogo_store_pkey PRIMARY KEY (c_folder_id, c_name)
);
CREATE TABLE sogo_acl
(
c_folder_id integer NOT NULL,
c_object character varying(255) NOT NULL,
c_uid character varying(255) NOT NULL,
c_role character varying(80) NOT NULL
);
CREATE INDEX sogo_acl_c_folder_id_idx ON sogo_acl(c_folder_id);
CREATE INDEX sogo_acl_c_uid_idx ON sogo_acl(c_uid);
CREATE TABLE sogo_quick_appointment
(
c_folder_id integer NOT NULL,
c_name character varying(255) NOT NULL,
c_uid character varying(255) NOT NULL,
c_startdate integer,
c_enddate integer,
c_cycleenddate integer,
c_title character varying(1000) NOT NULL,
c_participants text,
c_isallday integer,
c_iscycle integer,
c_cycleinfo text,
c_classification integer NOT NULL,
c_isopaque integer NOT NULL,
c_status integer NOT NULL,
c_priority integer,
c_location character varying(255),
c_orgmail character varying(255),
c_partmails text,
c_partstates text,
c_category character varying(255),
c_sequence integer,
c_component character varying(10) NOT NULL,
c_nextalarm integer,
c_description text,
CONSTRAINT sogo_quick_appointment_pkey PRIMARY KEY (c_folder_id, c_name)
);
CREATE TABLE sogo_quick_contact
(
c_folder_id integer NOT NULL,
c_name character varying(255) NOT NULL,
c_givenname character varying(255),
c_cn character varying(255),
c_sn character varying(255),
c_screenname character varying(255),
c_l character varying(255),
c_mail character varying(255),
c_o character varying(255),
c_ou character varying(255),
c_telephonenumber character varying(255),
c_categories character varying(255),
c_component character varying(10) NOT NULL,
CONSTRAINT sogo_quick_contact_pkey PRIMARY KEY (c_folder_id, c_name)
);
HERE
fi
#########################
# Merge per-folder tables
# Retrieve folder infos
psql -A -F " " -w -t -U $USER -h $HOST $DB -c "SELECT c_path, c_folder_id, c_folder_type, split_part(c_quick_location, '/', 5), \
split_part(c_location, '/', 5), split_part(c_acl_location, '/', 5) FROM \"$TABLE\" WHERE c_location IS NOT NULL" > $TABLEFILE
RET=$?
if [ $RET -ne 0 ]; then
echo "ERROR: postgresql returned error $RET" 1>&2
exit 1
fi
while read LINE
do
set $LINE
FOLDERID=$2
FOLDERTYPE=$3
QUICKTABLE=$4
STORETABLE=$5
ACLTABLE=$6
if [ "$FOLDERTYPE" != "Appointment" ] && [ "$FOLDERTYPE" != "Contact" ]; then
echo "ERROR: Unknown folder type $FOLDERTYPE, folder id $FOLDERID" 1>&2
exit 1
fi
# Merge content and acl
echo "INSERT INTO sogo_store(c_folder_id, $STOREFIELDS) SELECT $FOLDERID, $STOREFIELDS FROM $STORETABLE;" >> $SQLFILE
echo "INSERT INTO sogo_acl(c_folder_id, c_object, c_uid, c_role) SELECT $FOLDERID, c_object, c_uid, c_role FROM $ACLTABLE;" >> $SQLFILE
# Merge quick table
if [ "$FOLDERTYPE" = "Appointment" ]; then
echo "INSERT INTO sogo_quick_appointment(c_folder_id, $APPOINTMENTFIELDS) SELECT $FOLDERID, $APPOINTMENTFIELDS FROM $QUICKTABLE;" >> $SQLFILE
else
echo "INSERT INTO sogo_quick_contact(c_folder_id, $CONTACTFIELDS) SELECT $FOLDERID, $CONTACTFIELDS FROM $QUICKTABLE;" >> $SQLFILE
fi
# Drop migrated tables and update folder info
echo "DROP TABLE $QUICKTABLE;" >> $SQLFILE
echo "DROP TABLE $STORETABLE;" >> $SQLFILE
echo "DROP TABLE $ACLTABLE;" >> $SQLFILE
echo "UPDATE sogo_folder_info SET c_location = NULL, c_quick_location = NULL, c_acl_location = NULL WHERE c_folder_id = $FOLDERID;" >> $SQLFILE
echo >> $SQLFILE
done < $TABLEFILE
echo "Merging tables...."
psql -v ON_ERROR_STOP=1 -w -U $USER -h $HOST $DB < $SQLFILE
RET=$?
if [ $RET -ne 0 ]; then
echo "ERROR: postgresql returned error $RET" 1>&2
exit 1
fi
#########################
# Patch sogo.conf
if ! (grep -q "OCSStoreURL" /etc/sogo/sogo.conf); then
echo "Patching /etc/sogo/sogo.conf...."
# Generate properties OCSStoreURL and OCSAclURL
sed "s/\(.*\)OCSFolderInfoURL.*$/\0\n\1OCSStoreURL = \"postgresql:\/\/$USER:$PASSWORD@$HOST:$PORT\/$DB\/sogo_store\";\
\n\1OCSAclURL = \"postgresql:\/\/$USER:$PASSWORD@$HOST:$PORT\/$DB\/sogo_acl\";/g" -i /etc/sogo/sogo.conf
fi

View File

@ -1,6 +1,6 @@
/* SOGoCacheGCSFolder.h - this file is part of SOGo
*
* Copyright (C) 2012-2014 Inverse inc.
* Copyright (C) 2012-2016 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/* SOGoCacheGCSObject.h - this file is part of SOGo
*
* Copyright (C) 2012-2014 Inverse inc
* Copyright (C) 2012-2016 Inverse inc
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,6 @@
/* SOGoCacheGCSObject.m - this file is part of SOGo
*
* Copyright (C) 2012-2014 Inverse inc
* Copyright (C) 2012-2016 Inverse inc
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -25,7 +25,9 @@
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/NSObject+Utilities.h>
#import <SOGo/NSString+Utilities.h>
@ -124,6 +126,16 @@ static EOAttribute *textColumn = nil;
- (NSURL *) tableUrl
{
NSString *s;
s = [[NSUserDefaults standardUserDefaults] stringForKey: @"OCSCacheFolderURL"];
if (s)
{
tableUrl = [NSURL URLWithString: s];
[tableUrl retain];
}
if (!tableUrl)
{
tableUrl = [container tableUrl];
@ -247,6 +259,10 @@ static EOAttribute *textColumn = nil;
[self tableName],
newPath];
[sql appendFormat: @" WHERE c_path = '%@'", oldPath];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat: @" AND c_uid = '%@'", [[context activeUser] login]];
[self performBatchSQLQueries: [NSArray arrayWithObject: sql]];
}
}
@ -275,6 +291,10 @@ static EOAttribute *textColumn = nil;
else
[sql appendString: @", c_parent_path = NULL"];
[sql appendFormat: @" WHERE c_path = '%@'", oldPath];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat: @" AND c_uid = '%@'", [[context activeUser] login]];
[self performBatchSQLQueries: [NSArray arrayWithObject: sql]];
}
@ -379,6 +399,10 @@ static EOAttribute *textColumn = nil;
sql = [NSMutableString stringWithFormat:
@"SELECT * FROM %@ WHERE c_path = %@",
tableName, pathValue];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat: @" AND c_uid = '%@'", [[context activeUser] login]];
if (startVersion > -1)
[sql appendFormat: @" AND c_version > %d", (int)startVersion];
@ -413,6 +437,9 @@ static EOAttribute *textColumn = nil;
sql = [NSMutableString stringWithFormat:
@"SELECT * FROM %@ WHERE c_type = %d AND c_deleted <> 1", tableName, objectType];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat: @" AND c_uid = '%@'", [[context activeUser] login]];
if (startVersion > -1)
[sql appendFormat: @" AND c_version > %d", (int)startVersion];
@ -478,8 +505,9 @@ static EOAttribute *textColumn = nil;
- (NSException *) destroy
{
NSString *tableName, *pathValue, *sql;
NSString *tableName, *pathValue;
EOAdaptorChannel *channel;
NSMutableString *sql;
GCSChannelManager *cm;
NSException *result;
EOAdaptor *adaptor;
@ -493,11 +521,14 @@ static EOAttribute *textColumn = nil;
forAttribute: textColumn];
result = nil;
sql = [NSString stringWithFormat:
(@"DELETE FROM %@"
@" WHERE c_path = %@"),
tableName,
pathValue];
sql = [NSMutableString stringWithFormat:
(@"DELETE FROM %@"
@" WHERE c_path = %@"),
tableName,
pathValue];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat: @" AND c_uid = '%@'", [[context activeUser] login]];
result = [channel evaluateExpressionX: sql];
@ -512,14 +543,14 @@ static EOAttribute *textColumn = nil;
- (void) save
{
NSString *sql;
NSMutableString *sql;
NSData *content;
NSCalendarDate *now;
GCSChannelManager *cm;
EOAdaptor *adaptor;
EOAdaptorChannel *channel;
NSInteger creationDateValue, lastModifiedValue, deletedValue;
NSString *tableName, *pathValue, *parentPathValue, *propsValue;
NSString *tableName, *loginValue, *pathValue, *parentPathValue, *propsValue;
NSException *result;
if (!initialized)
@ -538,6 +569,8 @@ static EOAttribute *textColumn = nil;
adaptor = [[channel adaptorContext] adaptor];
pathValue = [adaptor formatValue: [self path]
forAttribute: textColumn];
loginValue = [adaptor formatValue: [[context activeUser] login]
forAttribute: textColumn];
lastModifiedValue = (NSInteger) [lastModified timeIntervalSince1970];
@ -563,30 +596,46 @@ static EOAttribute *textColumn = nil;
forAttribute: textColumn];
if (!parentPathValue)
parentPathValue = @"NULL";
sql = [NSString stringWithFormat:
(@"INSERT INTO %@"
@" (c_path, c_parent_path, c_type, c_creationdate, c_lastmodified,"
@" c_deleted, c_version, c_content)"
@" VALUES (%@, %@, %d, %d, %d, 0, 0, %@"
@")"),
tableName,
pathValue, parentPathValue, objectType,
(int)creationDateValue, (int)lastModifiedValue,
propsValue];
if ([GCSFolderManager singleStoreMode])
sql = [NSString stringWithFormat:
(@"INSERT INTO %@"
@" (c_uid, c_path, c_parent_path, c_type, c_creationdate, c_lastmodified,"
@" c_deleted, c_version, c_content)"
@" VALUES (%@, %@, %@, %d, %d, %d, 0, 0, %@"
@")"),
tableName,
loginValue, pathValue, parentPathValue, objectType,
(int)creationDateValue, (int)lastModifiedValue,
propsValue];
else
sql = [NSString stringWithFormat:
(@"INSERT INTO %@"
@" (c_path, c_parent_path, c_type, c_creationdate, c_lastmodified,"
@" c_deleted, c_version, c_content)"
@" VALUES (%@, %@, %d, %d, %d, 0, 0, %@"
@")"),
tableName,
pathValue, parentPathValue, objectType,
(int)creationDateValue, (int)lastModifiedValue,
propsValue];
isNew = NO;
}
else
{
version++;
deletedValue = (deleted ? 1 : 0);
sql = [NSString stringWithFormat:
(@"UPDATE %@"
@" SET c_lastmodified = %d, c_deleted = %d,"
@" c_version = %d, c_content = %@"
@" WHERE c_path = %@"),
tableName,
(int)lastModifiedValue, (int)deletedValue, (int)version, propsValue,
pathValue];
sql = [NSMutableString stringWithFormat:
(@"UPDATE %@"
@" SET c_lastmodified = %d, c_deleted = %d,"
@" c_version = %d, c_content = %@"
@" WHERE c_path = %@"),
tableName,
(int)lastModifiedValue, (int)deletedValue, (int)version, propsValue,
pathValue];
if ([GCSFolderManager singleStoreMode])
[sql appendFormat: @" AND c_uid = %@", loginValue];
}
result = [channel evaluateExpressionX: sql];

View File

@ -1778,11 +1778,18 @@ static NSArray *childRecordFields = nil;
userRoles = [roles objectEnumerator];
while ((currentRole = [userRoles nextObject]))
{
SQL = [NSString stringWithFormat: @"INSERT INTO %@"
@" (c_object, c_uid, c_role)"
@" VALUES ('/%@', '%@', '%@')",
[folder aclTableName],
objectPath, uid, currentRole];
if ([GCSFolderManager singleStoreMode])
SQL = [NSString stringWithFormat: @"INSERT INTO %@"
@" (c_object, c_uid, c_role, c_folder_id)"
@" VALUES ('/%@', '%@', '%@', %@)",
[folder aclTableName],
objectPath, uid, currentRole, [folder folderId]];
else
SQL = [NSString stringWithFormat: @"INSERT INTO %@"
@" (c_object, c_uid, c_role)"
@" VALUES ('/%@', '%@', '%@')",
[folder aclTableName],
objectPath, uid, currentRole];
[channel evaluateExpressionX: SQL];
}

View File

@ -26,6 +26,12 @@ MainUI_RESOURCE_FILES += \
SOGoProfile-oracle.sql \
OCSFolderInfo.sql \
OCSFolderInfo-oracle.sql \
OCSStore.sql \
OCSStore-mysql.sql \
OCSAcl-mysql.sql \
OCSAcl-postgresql.sql \
OCSCacheFolder-mysql.sql \
OCSCacheFolder-postgresql.sql
MainUI_LOCALIZED_RESOURCE_FILES += \
Locale Localizable.strings

View File

@ -0,0 +1,13 @@
--
-- (C) 2004-2005 SKYRIX Software AG
-- (C) 2006-2007 Inverse inc.
--
CREATE TABLE @{tableName} (
c_folder_id INTEGER NOT NULL,
c_object VARCHAR(255) NOT NULL,
c_uid VARCHAR(255) NOT NULL,
c_role VARCHAR(80) NOT NULL,
INDEX @{tableName}_c_folder_id_idx(c_folder_id),
INDEX @{tableName}_c_uid_idx(c_uid)
);

View File

@ -0,0 +1,14 @@
--
-- (C) 2004-2005 SKYRIX Software AG
-- (C) 2006-2007 Inverse inc.
--
CREATE TABLE @{tableName} (
c_folder_id INTEGER NOT NULL,
c_object VARCHAR(255) NOT NULL,
c_uid VARCHAR(255) NOT NULL,
c_role VARCHAR(80) NOT NULL
);
CREATE INDEX @{tableName}_c_folder_id_idx ON @{tableName}(c_folder_id);
CREATE INDEX @{tableName}_c_uid_idx ON @{tableName}(c_uid);

View File

@ -0,0 +1,17 @@
--
-- (C) 2004-2005 SKYRIX Software AG
-- (C) 2006-2007 Inverse inc.
--
CREATE TABLE @{tableName} (
c_uid VARCHAR(255) NOT NULL,
c_path VARCHAR(255) NOT NULL,
c_parent_path VARCHAR(255),
c_type TINYINT UNSIGNED NOT NULL,
c_creationdate INT NOT NULL,
c_lastmodified INT NOT NULL,
c_version INT NOT NULL DEFAULT 0,
c_deleted TINYINT NOT NULL DEFAULT 0,
c_content LONGTEXT,
CONSTRAINT @{tableName}_pkey PRIMARY KEY (c_uid, c_path)
);

View File

@ -0,0 +1,17 @@
--
-- (C) 2004-2005 SKYRIX Software AG
-- (C) 2006-2007 Inverse inc.
--
CREATE TABLE @{tableName} (
c_uid VARCHAR(255) NOT NULL,
c_path VARCHAR(255) NOT NULL,
c_parent_path VARCHAR(255),
c_type SMALLINT NOT NULL,
c_creationdate INT NOT NULL,
c_lastmodified INT NOT NULL,
c_version INT NOT NULL DEFAULT 0,
c_deleted SMALLINT NOT NULL DEFAULT 0,
c_content TEXT,
CONSTRAINT @{tableName}_pkey PRIMARY KEY (c_uid, c_path)
);

View File

@ -10,7 +10,7 @@ CREATE TABLE @{tableName} (
c_path3 VARCHAR(255) NULL, -- parts (for fast queries)
c_path4 VARCHAR(255) NULL, -- parts (for fast queries)
c_foldername VARCHAR(255) NOT NULL, -- last path component
c_location VARCHAR(2048) NOT NULL, -- URL to folder
c_location VARCHAR(2048) NULL, -- URL to folder
c_quick_location VARCHAR(2048) NULL, -- URL to quicktable of folder
c_acl_location VARCHAR(2048) NULL, -- URL to quicktable of folder
c_folder_type VARCHAR(255) NOT NULL -- the folder type ...

View File

@ -11,7 +11,7 @@ CREATE TABLE @{tableName} (
c_path3 VARCHAR(255) NULL, -- parts (for fast queries)
c_path4 VARCHAR(255) NULL, -- parts (for fast queries)
c_foldername VARCHAR(255) NOT NULL, -- last path component
c_location VARCHAR(2048) NOT NULL, -- URL to folder
c_location VARCHAR(2048) NULL, -- URL to folder
c_quick_location VARCHAR(2048) NULL, -- URL to quicktable of folder
c_acl_location VARCHAR(2048) NULL, -- URL to quicktable of folder
c_folder_type VARCHAR(255) NOT NULL -- the folder type ...

View File

@ -0,0 +1,15 @@
--
-- (C) 2004-2005 SKYRIX Software AG
-- (C) 2006-2007 Inverse inc.
--
CREATE TABLE @{tableName} (
c_folder_id INT NOT NULL,
c_name VARCHAR (255),
c_content MEDIUMTEXT NOT NULL,
c_creationdate INT NOT NULL,
c_lastmodified INT NOT NULL,
c_version INT NOT NULL,
c_deleted INT NULL,
CONSTRAINT @{tableName}_pkey PRIMARY KEY (c_folder_id, c_name)
);

View File

@ -0,0 +1,15 @@
--
-- (C) 2004-2005 SKYRIX Software AG
-- (C) 2006-2007 Inverse inc.
--
CREATE TABLE @{tableName} (
c_folder_id INT NOT NULL,
c_name VARCHAR (255),
c_content TEXT NOT NULL,
c_creationdate INT NOT NULL,
c_lastmodified INT NOT NULL,
c_version INT NOT NULL,
c_deleted INT NULL,
CONSTRAINT @{tableName}_pkey PRIMARY KEY (c_folder_id, c_name)
);