diff options
author | stuconnolly <stuart02@gmail.com> | 2010-10-07 18:56:33 +0000 |
---|---|---|
committer | stuconnolly <stuart02@gmail.com> | 2010-10-07 18:56:33 +0000 |
commit | 44a5f9e552b3d5e1f9ef1c6d11f34e893d67e85b (patch) | |
tree | c833ba970d8cae5f756a31bc274e365c0a44b3bf /Source/SPServerSupport.m | |
parent | 95d2e4acc393e91aa70ed4c71daa1f776454a936 (diff) | |
download | sequelpro-44a5f9e552b3d5e1f9ef1c6d11f34e893d67e85b.tar.gz sequelpro-44a5f9e552b3d5e1f9ef1c6d11f34e893d67e85b.tar.bz2 sequelpro-44a5f9e552b3d5e1f9ef1c6d11f34e893d67e85b.zip |
Various improvements to server capability/version checking, including:
- Add a new ServerSupport class, for which an instance is created upon each new connection and is then subsequently accessible via SPDatabaseDocument.
- Replace the majority of manual version checking with calls to properties in the above new class.
- Improve the user manager's compatibility with MySQL 3 and 4 servers. Fixes issue #811
Other changes include:
- Disable the encoding popup button when adding a new table or database to servers running pre MySQL 4.1 as it only contains one option, 'Default'.
- Fix various potential memory leaks discovered during static analysis.
- General tidy up and comments.
Diffstat (limited to 'Source/SPServerSupport.m')
-rw-r--r-- | Source/SPServerSupport.m | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/Source/SPServerSupport.m b/Source/SPServerSupport.m new file mode 100644 index 00000000..3f8227d9 --- /dev/null +++ b/Source/SPServerSupport.m @@ -0,0 +1,311 @@ +// +// $Id$ +// +// SPServerSupport.m +// sequel-pro +// +// Created by Stuart Connolly (stuconnolly.com) on September 23, 2010 +// Copyright (c) 2010 Stuart Connolly. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at <http://code.google.com/p/sequel-pro/> + +#import "SPServerSupport.h" +#import <objc/runtime.h> + +@interface SPServerSupport (PrivateAPI) + +- (void)_invalidate; +- (NSComparisonResult)_compareServerMajorVersion:(NSInteger)majorVersionA + minor:(NSInteger)minorVersionA + release:(NSInteger)releaseVersionA + withServerMajorVersion:(NSInteger)majorVersionB + minor:(NSInteger)minorVersionB + release:(NSInteger)releaseVersionB; + +@end + +@implementation SPServerSupport + +@synthesize isMySQL3; +@synthesize isMySQL4; +@synthesize isMySQL5; +@synthesize isMySQL6; +@synthesize supportsInformationSchema; +@synthesize supportsShowCharacterSet; +@synthesize supportsCharacterSetDatabaseVar; +@synthesize supportsPost41CharacterSetHandling; +@synthesize supportsCreateUser; +@synthesize supportsDropUser; +@synthesize supportsFullDropUser; +@synthesize supportsUserMaxVars; +@synthesize supportsShowPrivileges; +@synthesize supportsInformationSchemaEngines; +@synthesize supportsPre41StorageEngines; +@synthesize supportsBlackholeStorageEngine; +@synthesize supportsArchiveStorageEngine; +@synthesize supportsCSVStorageEngine; +@synthesize supportsTriggers; +@synthesize supportsIndexKeyBlockSize; +@synthesize serverMajorVersion; +@synthesize serverMinorVersion; +@synthesize serverReleaseVersion; + +#pragma mark - +#pragma mark Initialization + +/** + * Creates and returns an instance of SPServerSupport with the supplied version numbers. The caller is + * responsible it's memory. + * + * @param majorVersion The major version number of the server + * @param minorVersion The minor version number of the server + * @param releaseVersiod The release version number of the server + * + * @return The initializes SPServerSupport instance + */ +- (id)initWithMajorVersion:(NSInteger)majorVersion minor:(NSInteger)minorVersion release:(NSInteger)releaseVersion +{ + if ((self == [super init])) { + + serverMajorVersion = majorVersion; + serverMinorVersion = minorVersion; + serverReleaseVersion = releaseVersion; + + // Determine what the server supports + [self evaluate]; + } + + return self; +} + +#pragma mark - +#pragma mark Public API + +/** + * Performs the actual version based comparisons to determine what functionaity the server supports. This + * method is called automatically as part of the designated initializer (initWithMajorVersion:major:minor:release:) + * and shouldn't really need to be called again throughout a connection's lifetime. + * + * Note that for the sake of simplicity this method does not try to be smart in that it does not assume + * the presence of functionality based on a previous version check. This allows adding new ivars in the + * future a matter of simply performing a new version comparison. + * + * To add a new metod for determining a server's support for specific functionality, simply add a new + * (read only) ivar with the prefix 'supports' and peform the version checking within this method. + */ +- (void)evaluate +{ + // By default, assumme the server doesn't support anything + [self _invalidate]; + + isMySQL3 = (serverMajorVersion == 3); + isMySQL4 = (serverMajorVersion == 4); + isMySQL5 = (serverMajorVersion == 5); + isMySQL6 = (serverMajorVersion == 6); + + // The information schema database wasn't added until MySQL 5 + supportsInformationSchema = (serverMajorVersion >= 5); + + // The SHOW CHARACTER SET statement wasn't added until MySQL 4.1.0 + supportsShowCharacterSet = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:0]; + + // The variable 'character_set_database' wasn't added until MySQL 4.1.1 + supportsCharacterSetDatabaseVar = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:1]; + + // As of MySQL 4.1 encoding support was greatly improved + supportsPost41CharacterSetHandling = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:0]; + + // The table information_schema.engines wasn't added until MySQL 5.1.5 + supportsInformationSchemaEngines = [self isEqualToOrGreaterThanMajorVersion:5 minor:1 release:1]; + + // The CREATE USER statement wasn't added until MySQL 5.0.2 + supportsCreateUser = [self isEqualToOrGreaterThanMajorVersion:5 minor:0 release:2]; + + // The DROP USER statement wasn't added until MySQL 4.1.1 + supportsDropUser = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:1]; + + // Similarly before MySQL 5.0.2 the DROP USER statement only removed users with no privileges + supportsFullDropUser = [self isEqualToOrGreaterThanMajorVersion:5 minor:0 release:2]; + + // The maximum user variable columns (within mysql.user) weren't added until MySQL 4.0.2 + supportsUserMaxVars = [self isEqualToOrGreaterThanMajorVersion:4 minor:0 release:2]; + + // The SHOW PRIVILEGES statement wasn't added until MySQL 4.1.0 + supportsShowPrivileges = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:0]; + + // Before MySQL 4.1 the MEMORY engine was known as HEAP and the ISAM engine was available + supportsPre41StorageEngines = (![self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:0]); + + // The BLACKHOLE storage engine wasn't added until MySQL 4.1.11 + supportsBlackholeStorageEngine = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:11]; + + // The ARCHIVE storage engine wasn't added until MySQL 4.1.3 + supportsArchiveStorageEngine = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:3]; + + // The CSV storage engine wasn't added until MySQL 4.1.4 + supportsCSVStorageEngine = [self isEqualToOrGreaterThanMajorVersion:4 minor:1 release:4]; + + // Support for triggers wasn't added until MySQL 5.0.2 + supportsTriggers = [self isEqualToOrGreaterThanMajorVersion:5 minor:0 release:2]; + + // Support for specifying an index's key block size wasn't added until MySQL 5.1.10 + supportsIndexKeyBlockSize = [self isEqualToOrGreaterThanMajorVersion:5 minor:1 release:10]; +} + +/** + * Convenience method provided as an easy way to determine whether the currently connected server version + * is equal to or greater than the supplied version numbers. + * + * This method should only be used in the case that the build in support ivars don't cover the version/functionality + * checking that is required. + * + * @param majorVersion The major version number of the server + * @param minorVersion The minor version number of the server + * @param releaseVersiod The release version number of the server + * + * @return A BOOL indicating the result of the comparison. + */ +- (BOOL)isEqualToOrGreaterThanMajorVersion:(NSInteger)majorVersion minor:(NSInteger)minorVersion release:(NSInteger)releaseVersion; +{ + return ([self _compareServerMajorVersion:serverMajorVersion + minor:serverMinorVersion + release:serverReleaseVersion + withServerMajorVersion:majorVersion + minor:minorVersion + release:releaseVersion] > NSOrderedAscending); +} + +/** + * Provides a general description of this object instance. Note that this should only be used for debugging purposes. + * + * @return The string describing the object instance + */ +- (NSString *)description +{ + unsigned int i; + NSString *description = [NSMutableString stringWithFormat:@"<%@: Server is MySQL version %d.%d.%d. Supports:\n", [self className], serverMajorVersion, serverMinorVersion, serverReleaseVersion]; + + Ivar *vars = class_copyIvarList([self class], &i); + + for (NSUInteger j = 0; j < i; j++) + { + NSString *varName = [NSString stringWithUTF8String:ivar_getName(vars[j])]; + + if ([varName hasPrefix:@"supports"]) { + [description appendFormat:@"\t%@ = %@\n", varName, ((BOOL)object_getIvar(self, vars[j])) ? @"YES" : @"NO"]; + } + } + + [description appendString:@">"]; + + free(vars); + + return description; +} + +#pragma mark - +#pragma mark Private API + +/** + * Invalidates all knowledge of what we know the server supports by simply reseting all ivars to their + * original state, that is, it doesn't support anything. + */ +- (void)_invalidate +{ + isMySQL3 = NO; + isMySQL4 = NO; + isMySQL5 = NO; + isMySQL6 = NO; + + supportsInformationSchema = NO; + supportsShowCharacterSet = NO; + supportsCharacterSetDatabaseVar = NO; + supportsPost41CharacterSetHandling = NO; + supportsCreateUser = NO; + supportsDropUser = NO; + supportsFullDropUser = NO; + supportsUserMaxVars = NO; + supportsShowPrivileges = NO; + supportsInformationSchemaEngines = NO; + supportsPre41StorageEngines = NO; + supportsBlackholeStorageEngine = NO; + supportsArchiveStorageEngine = NO; + supportsCSVStorageEngine = NO; + supportsTriggers = NO; + supportsIndexKeyBlockSize = NO; +} + +/** + * Compares the supplied version numbers to determine their order. + * + * Note that this method assumes (when comparing MySQL version numbers) that release verions in the form + * XX are larger than X. For example, version 5.0.18 is greater than version 5.0.8 + * + * @param majorVersionA The major version number of server A + * @param minorVersionA The minor version number of server A + * @param releaseVersionA The release version number of server A + * @param majorVersionB The major version number of server B + * @param minorVersionB The minor version number of server B + * @param releaseVersionB The release version number of server B + * + * @return One of NSComparisonResult constants indicating the order of the comparison + */ +- (NSComparisonResult)_compareServerMajorVersion:(NSInteger)majorVersionA + minor:(NSInteger)minorVersionA + release:(NSInteger)releaseVersionA + withServerMajorVersion:(NSInteger)majorVersionB + minor:(NSInteger)minorVersionB + release:(NSInteger)releaseVersionB +{ + if (majorVersionA > majorVersionB) return NSOrderedDescending; + + if (majorVersionA < majorVersionB) return NSOrderedAscending; + + // The major versions are the same so move to checking the minor versions + if (minorVersionA > minorVersionB) return NSOrderedDescending; + + if (minorVersionA < minorVersionB) return NSOrderedAscending; + + // The minor versions are the same so move to checking the release versions + if (releaseVersionA > releaseVersionB) return NSOrderedDescending; + + if (releaseVersionA < releaseVersionB) return NSOrderedAscending; + + // Both version numbers are the same + return NSOrderedSame; +} + +#pragma mark - +#pragma mark Other + +/** + * Dealloc. Invalidate all ivars. + */ +- (void)dealloc +{ + // Reset version integers + serverMajorVersion = -1; + serverMinorVersion = -1; + serverReleaseVersion = -1; + + // Invalidate all ivars + [self _invalidate]; + + [super dealloc]; +} + +@end |