aboutsummaryrefslogtreecommitdiffstats
path: root/Source/CMMCPConnection.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CMMCPConnection.m')
-rw-r--r--Source/CMMCPConnection.m1364
1 files changed, 0 insertions, 1364 deletions
diff --git a/Source/CMMCPConnection.m b/Source/CMMCPConnection.m
deleted file mode 100644
index 9848101e..00000000
--- a/Source/CMMCPConnection.m
+++ /dev/null
@@ -1,1364 +0,0 @@
-//
-// $Id$
-//
-// CMMCPConnection.m
-// sequel-pro
-//
-// Created by lorenz textor (lorenz@textor.ch) on Wed Sept 21 2005.
-// Copyright (c) 2002-2003 Lorenz Textor. 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 "CMMCPConnection.h"
-#import "SPStringAdditions.h"
-#include <unistd.h>
-#include <setjmp.h>
-#include <mach/mach_time.h>
-
-static jmp_buf pingTimeoutJumpLocation;
-static void forcePingTimeout(int signalNumber);
-
-@interface CMMCPConnection(hidden)
-- (void)getServerVersionString;
-@end
-
-@implementation CMMCPConnection(hidden)
-- (void)getServerVersionString
-{
- if( mConnected ) {
- CMMCPResult *theResult;
- theResult = [self queryString:@"SHOW VARIABLES LIKE 'version'"];
- if ([theResult numOfRows]) {
- [theResult dataSeek:0];
- serverVersionString = [[NSString stringWithString:[[theResult fetchRowAsArray] objectAtIndex:1]] retain];
- }
- }
-}
-@end
-
-
-@implementation CMMCPConnection
-
-/*
- * Override the normal init methods, extending them to also init additional details,
- * and to store details of the initialised connection to allow reconnection as method.
- * Note this also behaves differently from the standard MCPKit connection methods -
- * passwords are passed separately, and connections are not automatically made on init.
- */
-- (id) init
-{
- [self initSPExtensions];
- self = [super init];
- serverVersionString = nil;
- return self;
-}
-- (id) initToHost:(NSString *) host withLogin:(NSString *) login usingPort:(int) port
-{
- [self initSPExtensions];
-
- self = [super init];
- mEncoding = NSISOLatin1StringEncoding;
- mConnection = mysql_init(mConnection);
- mConnected = NO;
- if (mConnection == NULL) {
- [self autorelease];
- return nil;
- }
-
- mConnectionFlags = kMCPConnectionDefaultOption;
-
- if (!host) host = @"";
- if (!login) login = @"";
-
- connectionHost = [[NSString alloc] initWithString:host];
- connectionLogin = [[NSString alloc] initWithString:login];
- connectionPort = port;
- connectionSocket = nil;
-
- return self;
-}
-- (id) initToSocket:(NSString *) socket withLogin:(NSString *) login
-{
- [self initSPExtensions];
- self = [super init];
- mEncoding = NSISOLatin1StringEncoding;
- mConnection = mysql_init(mConnection);
- mConnected = NO;
- if (mConnection == NULL) {
- [self autorelease];
- return nil;
- }
-
- mConnectionFlags = kMCPConnectionDefaultOption;
-
- if (!socket || ![socket length]) {
- socket = [self findSocketPath];
- if (!socket) socket = @"";
- }
- if (!login) login = @"";
-
- connectionHost = nil;
- connectionLogin = [[NSString alloc] initWithString:login];
- connectionSocket = [[NSString alloc] initWithString:socket];
- connectionPort = 0;
-
- return self;
-}
-
-
-/*
- * Instantiate extra variables and load the connection error dialog for potential use.
- */
-- (void) initSPExtensions
-{
- parentWindow = nil;
- connectionHost = nil;
- connectionLogin = nil;
- connectionSocket = nil;
- connectionPassword = nil;
- connectionKeychainName = nil;
- connectionKeychainAccount = nil;
- keepAliveTimer = nil;
- connectionTunnel = nil;
- connectionTimeout = [[[NSUserDefaults standardUserDefaults] objectForKey:@"ConnectionTimeout"] intValue];
- if (!connectionTimeout) connectionTimeout = 10;
- useKeepAlive = [[[NSUserDefaults standardUserDefaults] objectForKey:@"UseKeepAlive"] doubleValue];
- keepAliveInterval = [[[NSUserDefaults standardUserDefaults] objectForKey:@"KeepAliveInterval"] doubleValue];
- if (!keepAliveInterval) keepAliveInterval = 0;
- lastKeepAliveSuccess = nil;
- connectionThreadId = 0;
- maxAllowedPacketSize = -1;
- lastQueryExecutionTime = 0;
- lastQueryErrorId = 0;
- lastQueryErrorMessage = nil;
- lastQueryAffectedRows = 0;
- if (![NSBundle loadNibNamed:@"ConnectionErrorDialog" owner:self]) {
- NSLog(@"Connection error dialog could not be loaded; connection failure handling will not function correctly.");
- }
-
- willQueryStringSEL = @selector(willQueryString:);
- stopKeepAliveTimerSEL = @selector(stopKeepAliveTimer);
- startKeepAliveTimerResettingStateSEL = @selector(startKeepAliveTimerResettingState:);
- cStringSEL = @selector(cStringFromString:);
-
- cStringPtr = [self methodForSelector:cStringSEL];
- stopKeepAliveTimerPtr = [self methodForSelector:stopKeepAliveTimerSEL];
- startKeepAliveTimerResettingStatePtr = [self methodForSelector:startKeepAliveTimerResettingStateSEL];
-
-}
-
-/*
- * Sets the password to be stored locally.
- * Providing a keychain name is much more secure.
- */
-- (BOOL) setPassword:(NSString *)thePassword
-{
- if (connectionPassword) [connectionPassword release], connectionPassword = nil;
- if (connectionKeychainName) [connectionKeychainName release], connectionKeychainName = nil;
- if (connectionKeychainAccount) [connectionKeychainAccount release], connectionKeychainAccount = nil;
-
- if (!thePassword) thePassword = @"";
-
- connectionPassword = [[NSString alloc] initWithString:thePassword];
-
- return YES;
-}
-
-/*
- * Sets the keychain name to use to retrieve the password. This is the recommended and
- * secure way of supplying a password to the SSH tunnel.
- */
-- (BOOL) setPasswordKeychainName:(NSString *)theName account:(NSString *)theAccount
-{
- if (connectionPassword) [connectionPassword release], connectionPassword = nil;
- if (connectionKeychainName) [connectionKeychainName release], connectionKeychainName = nil;
- if (connectionKeychainAccount) [connectionKeychainAccount release], connectionKeychainAccount = nil;
-
- connectionKeychainName = [[NSString alloc] initWithString:theName];
- connectionKeychainAccount = [[NSString alloc] initWithString:theAccount];
-
- return YES;
-}
-
-/*
- * Sets or updates the connection port - for use with tunnels.
- */
-- (BOOL) setPort:(int) thePort
-{
- connectionPort = thePort;
-
- return YES;
-}
-
-/*
- * Set a SSH tunnel object to connect through. This object will be retained locally,
- * and will be automatically connected/connection checked/reconnected/disconnected
- * together with the main connection.
- */
-- (BOOL) setSSHTunnel:(SPSSHTunnel *)theTunnel
-{
- connectionTunnel = theTunnel;
- [connectionTunnel retain];
-
- currentSSHTunnelState = [connectionTunnel state];
- [connectionTunnel setConnectionStateChangeSelector:@selector(sshTunnelStateChange:) delegate:self];
-
- return YES;
-}
-
-/*
- * Add a new connection method, intended for use with the init methods above.
- * Uses the stored details to instantiate a connection to the specified server,
- * including custom timeouts - used for pings, not for long-running commands.
- */
-- (BOOL) connect
-{
- const char *theLogin = [self cStringFromString:connectionLogin];
- const char *theHost;
- const char *thePass;
- const char *theSocket;
- void *theRet;
-
- // Ensure that a password method has been provided
- if (connectionKeychainName == nil && connectionPassword == nil) return NO;
-
- // Disconnect if a connection is already active
- if (mConnected) {
- [self disconnect];
- mConnection = mysql_init(NULL);
- if (mConnection == NULL) return NO;
- }
-
- // Ensure the custom timeout option is set
- if (mConnection != NULL) {
- mysql_options(mConnection, MYSQL_OPT_CONNECT_TIMEOUT, (const void *)&connectionTimeout);
- }
-
- // Set the host as appropriate
- if (!connectionHost || ![connectionHost length]) {
- theHost = NULL;
- } else {
- theHost = [self cStringFromString:connectionHost];
- }
-
- // Use the default socket if none is set, or set appropriately
- if (connectionSocket == nil || ![connectionSocket length]) {
- theSocket = kMCPConnectionDefaultSocket;
- } else {
- theSocket = [self cStringFromString:connectionSocket];
- }
-
- // Select the password from the provided method
- if (connectionKeychainName) {
- KeyChain *keychain;
- keychain = [[KeyChain alloc] init];
- thePass = [self cStringFromString:[keychain getPasswordForName:connectionKeychainName account:connectionKeychainAccount]];
- [keychain release];
- } else {
- thePass = [self cStringFromString:connectionPassword];
- }
-
- // Connect
- theRet = mysql_real_connect(mConnection, theHost, theLogin, thePass, NULL, connectionPort, theSocket, mConnectionFlags);
- thePass = NULL;
- if (theRet != mConnection) {
- [self setLastErrorMessage:nil];
- lastQueryErrorId = mysql_errno(mConnection);
- return mConnected = NO;
- }
-
- mConnected = YES;
- mEncoding = [MCPConnection encodingForMySQLEncoding:mysql_character_set_name(mConnection)];
- connectionThreadId = mConnection->thread_id;
- [self timeZone]; // Getting the timezone used by the server.
-
- isMaxAllowedPacketEditable = [self isMaxAllowedPacketEditable];
-
- if (![self fetchMaxAllowedPacket]) {
- [self setLastErrorMessage:nil];
- lastQueryErrorId = mysql_errno(mConnection);
- return mConnected = NO;
- }
-
- // Register notification if a query was sent to the MySQL connection
- // to be able to identify the sender of that query
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(willPerformQuery:)
- name:@"SMySQLQueryWillBePerformed" object:nil];
-
- [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"ConsoleEnableLogging" options:NSKeyValueObservingOptionNew context:NULL];
-
- // Init 'consoleLoggingEnabled'
- consoleLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"ConsoleEnableLogging"];
-
- // Start the keepalive timer
- [self startKeepAliveTimerResettingState:YES];
-
- return mConnected;
-}
-
-
-/*
- * Override the stored disconnection method to ensure that disconnecting clears stored timers.
- */
-- (void) disconnect
-{
- [super disconnect];
-
- if (connectionTunnel) {
- [connectionTunnel disconnect];
- if (delegate) [delegate setTitlebarStatus:@"SSH Disconnected"];
- //[delegate setStatusIconToImageWithName:@"ssh-disconnected"];
- }
-
- if( serverVersionString != nil ) {
- [serverVersionString release];
- serverVersionString = nil;
- }
-
- [self stopKeepAliveTimer];
-}
-
-/*
- * return the server major version or -1 on fail
- */
-- (int)serverMajorVersion
-{
-
- if( mConnected ) {
- if( serverVersionString == nil ) {
- [self getServerVersionString];
- }
- if( serverVersionString != nil ) {
- return [[[serverVersionString componentsSeparatedByString:@"."] objectAtIndex:0] intValue];
- }
- }
- return -1;
-}
-
-/*
- * return the server minor version or -1 on fail
- */
-- (int)serverMinorVersion
-{
-
- if( mConnected ) {
- if( serverVersionString == nil ) {
- [self getServerVersionString];
- }
- if( serverVersionString != nil ) {
- return [[[serverVersionString componentsSeparatedByString:@"."] objectAtIndex:1] intValue];
- }
- }
- return -1;
-}
-
-/*
- * return the server release version or -1 on fail
- */
-- (int)serverReleaseVersion
-{
- if( mConnected ) {
- if( serverVersionString == nil ) {
- [self getServerVersionString];
- }
- if( serverVersionString != nil ) {
- NSString *s = [[serverVersionString componentsSeparatedByString:@"."] objectAtIndex:2];
- return [[[s componentsSeparatedByString:@"-"] objectAtIndex:0] intValue];
- }
- }
- return -1;
-}
-
-
-/*
- * Reconnect to the currently "active" - but possibly disconnected - connection, using the
- * stored details.
- * Error checks extensively - if this method fails, it will ask how to proceed and loop depending
- * on the status, not returning control until either a connection has been established or
- * the connection and document have been closed.
- */
-- (BOOL) reconnect
-{
- NSString *currentEncoding = nil;
- BOOL currentEncodingUsesLatin1Transport = NO;
- NSString *currentDatabase = nil;
-
- // Store the current database and encoding so they can be re-set if reconnection was successful
- if (delegate && [delegate valueForKey:@"selectedDatabase"]) {
- currentDatabase = [NSString stringWithString:[delegate valueForKey:@"selectedDatabase"]];
- }
- if (delegate && [delegate valueForKey:@"_encoding"]) {
- currentEncoding = [NSString stringWithString:[delegate valueForKey:@"_encoding"]];
- }
- if (delegate && [delegate respondsToSelector:@selector(connectionEncodingViaLatin1)]) {
- currentEncodingUsesLatin1Transport = [delegate connectionEncodingViaLatin1];
- }
-
- // Close the connection if it exists.
- if (mConnected) {
- mysql_close(mConnection);
- mConnection = NULL;
- }
- mConnected = NO;
-
- // If there is a tunnel, ensure it's disconnected and attempt to reconnect it in blocking fashion
- if (connectionTunnel) {
- [connectionTunnel setConnectionStateChangeSelector:nil delegate:nil];
- if ([connectionTunnel state] != SPSSH_STATE_IDLE) [connectionTunnel disconnect];
- [connectionTunnel connect];
-
- if (delegate) [delegate setTitlebarStatus:@"SSH Connecting…"];
- //[delegate setStatusIconToImageWithName:@"ssh-connecting"];
-
- NSDate *tunnelStartDate = [NSDate date], *interfaceInteractionTimer;
-
- // Allow the tunnel to attempt to connect in a loop
- while (1) {
- if ([connectionTunnel state] == SPSSH_STATE_CONNECTED) {
- if (delegate) [delegate setTitlebarStatus:@"SSH Connected"];
- //[delegate setStatusIconToImageWithName:@"ssh-connected"];
- connectionPort = [connectionTunnel localPort];
- break;
- }
- if ([[NSDate date] timeIntervalSinceDate:tunnelStartDate] > (connectionTimeout + 1)) {
- [connectionTunnel disconnect];
- if (delegate) [delegate setTitlebarStatus:@"SSH Disconnected"];
- //[delegate setStatusIconToImageWithName:@"ssh-disconnected"];
- break;
- }
-
- // Process events for a short time, allowing dialogs to be shown but waiting for the tunnel
- interfaceInteractionTimer = [NSDate date];
- [[NSRunLoop currentRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
- tunnelStartDate = [tunnelStartDate addTimeInterval:([[NSDate date] timeIntervalSinceDate:interfaceInteractionTimer] - 0.25)];
- }
- currentSSHTunnelState = [connectionTunnel state];
- [connectionTunnel setConnectionStateChangeSelector:@selector(sshTunnelStateChange:) delegate:self];
- }
-
- if (!connectionTunnel || [connectionTunnel state] == SPSSH_STATE_CONNECTED) {
-
- // Attempt to reinitialise the connection - if this fails, it will still be set to NULL.
- if (mConnection == NULL) {
- mConnection = mysql_init(NULL);
- }
-
- if (mConnection != NULL) {
-
- // Set a connection timeout for the new connection
- mysql_options(mConnection, MYSQL_OPT_CONNECT_TIMEOUT, (const void *)&connectionTimeout);
-
- // Attempt to reestablish the connection
- [self connect];
- }
- }
-
- // If the connection was successfully established, reselect the old database and encoding if appropriate.
- if (mConnected) {
- if (currentDatabase) {
- [self selectDB:currentDatabase];
- }
- if (currentEncoding) {
- [self queryString:[NSString stringWithFormat:@"/*!40101 SET NAMES '%@' */", currentEncoding]];
- [self setEncoding:[CMMCPConnection encodingForMySQLEncoding:[currentEncoding UTF8String]]];
- if (currentEncodingUsesLatin1Transport) {
- [self queryString:@"/*!40101 SET CHARACTER_SET_RESULTS=latin1 */"];
- }
- }
- } else if (parentWindow) {
- if (connectionTunnel && [connectionTunnel state] != SPSSH_STATE_CONNECTED) {
- [self setLastErrorMessage:@"(Could not connect because the Sequel Pro SSH Tunnel could not be reestablished)"];
- } else {
- [self setLastErrorMessage:nil];
- }
-
- // If the connection was not successfully established, ask how to proceed.
- [NSApp beginSheet:connectionErrorDialog modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
- int connectionErrorCode = [NSApp runModalForWindow:connectionErrorDialog];
- [NSApp endSheet:connectionErrorDialog];
- [connectionErrorDialog orderOut:nil];
-
- switch (connectionErrorCode) {
-
- // Should disconnect
- case 2:
- [parentWindow close];
- return NO;
-
- // Should retry
- default:
- return [self reconnect];
- }
- }
-
- return mConnected;
-}
-
-
-/*
- * Set the parent window of the connection for use with dialogs.
- */
-- (void)setParentWindow:(NSWindow *)theWindow
-{
- parentWindow = theWindow;
-}
-
-/*
- * Handle any state changes in the associated SSH Tunnel
- */
-- (void)sshTunnelStateChange:(SPSSHTunnel *)theTunnel
-{
- int newState = [theTunnel state];
-
- if (delegate && [delegate respondsToSelector:@selector(setStatusIconToImageWithName:)]) {
- if (newState == SPSSH_STATE_IDLE) [delegate setTitlebarStatus:@"SSH Disconnected"];
- else if (newState == SPSSH_STATE_CONNECTED) [delegate setTitlebarStatus:@"SSH Connected"];
- else [delegate setTitlebarStatus:@"SSH Connecting…"];
-
-
-// if (newState == SPSSH_STATE_IDLE) [delegate setStatusIconToImageWithName:@"ssh-disconnected"];
-// else if (newState == SPSSH_STATE_CONNECTED) [delegate setStatusIconToImageWithName:@"ssh-connected"];
-// else [delegate setStatusIconToImageWithName:@"ssh-connecting"];
- }
-
- // Restart the tunnel if it dies
- if (mConnected && newState == SPSSH_STATE_IDLE && currentSSHTunnelState == SPSSH_STATE_CONNECTED) {
- currentSSHTunnelState = newState;
- [connectionTunnel setConnectionStateChangeSelector:nil delegate:nil];
- [self reconnect];
- return;
- }
-
- currentSSHTunnelState = newState;
-}
-
-
-/*
- * Ends an existing modal session
- */
-- (IBAction) closeSheet:(id)sender
-{
- [NSApp stopModalWithCode:[sender tag]];
-}
-
-/*
- * Determines whether a supplied error number can be classed as a connection
- * error.
- */
-+ (BOOL) isErrorNumberConnectionError:(int)theErrorNumber
-{
-
- switch (theErrorNumber) {
- case 2001: // CR_SOCKET_CREATE_ERROR
- case 2002: // CR_CONNECTION_ERROR
- case 2003: // CR_CONN_HOST_ERROR
- case 2004: // CR_IPSOCK_ERROR
- case 2005: // CR_UNKNOWN_HOST
- case 2006: // CR_SERVER_GONE_ERROR
- case 2007: // CR_VERSION_ERROR
- case 2009: // CR_WRONG_HOST_INFO
- case 2012: // CR_SERVER_HANDSHAKE_ERR
- case 2013: // CR_SERVER_LOST
- case 2027: // CR_MALFORMED_PACKET
- case 2032: // CR_DATA_TRUNCATED
- case 2047: // CR_CONN_UNKNOW_PROTOCOL
- case 2048: // CR_INVALID_CONN_HANDLE
- case 2050: // CR_FETCH_CANCELED
- case 2055: // CR_SERVER_LOST_EXTENDED
- return YES;
- }
-
- return NO;
-}
-
-/*
- * Gets a proper NSStringEncoding according to the given MySQL charset.
- *
- * MySQL 4.0 offers this charsets:
- * big5 cp1251 cp1257 croat czech danish dec8 dos estonia euc_kr gb2312 gbk german1
- * greek hebrew hp8 hungarian koi8_ru koi8_ukr latin1 latin1_de latin2 latin5 sjis
- * swe7 tis620 ujis usa7 win1250 win1251ukr
- *
- * WARNING : incomplete implementation. Please, send your fixes.
- */
-+ (NSStringEncoding) encodingForMySQLEncoding:(const char *) mysqlEncoding
-{
- // Unicode encodings:
- if (!strncmp(mysqlEncoding, "utf8", 4)) {
- return NSUTF8StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "ucs2", 4)) {
- return NSUnicodeStringEncoding;
- }
-
- // Roman alphabet encodings:
- if (!strncmp(mysqlEncoding, "ascii", 5)) {
- return NSASCIIStringEncoding;
- }
- if (!strncmp(mysqlEncoding, "latin1", 6)) {
- return NSISOLatin1StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "macroman", 8)) {
- return NSMacOSRomanStringEncoding;
- }
-
- // Roman alphabet with central/east european additions:
- if (!strncmp(mysqlEncoding, "latin2", 6)) {
- return NSISOLatin2StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "cp1250", 6)) {
- return NSWindowsCP1250StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "win1250", 7)) {
- return NSWindowsCP1250StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "cp1257", 6)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsBalticRim);
- }
-
- // Additions for Turkish:
- if (!strncmp(mysqlEncoding, "latin5", 6)) {
- return NSWindowsCP1254StringEncoding;
- }
-
- // Greek:
- if (!strncmp(mysqlEncoding, "greek", 5)) {
- return NSWindowsCP1253StringEncoding;
- }
-
- // Cyrillic:
- if (!strncmp(mysqlEncoding, "win1251ukr", 6)) {
- return NSWindowsCP1251StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "cp1251", 6)) {
- return NSWindowsCP1251StringEncoding;
- }
- if (!strncmp(mysqlEncoding, "koi8_ru", 6)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R);
- }
- if (!strncmp(mysqlEncoding, "koi8_ukr", 6)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R);
- }
-
- // Arabic:
- if (!strncmp(mysqlEncoding, "cp1256", 6)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsArabic);
- }
-
- // Hebrew:
- if (!strncmp(mysqlEncoding, "hebrew", 6)) {
- CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinHebrew);
- }
-
- // Asian:
- if (!strncmp(mysqlEncoding, "ujis", 4)) {
- return NSJapaneseEUCStringEncoding;
- }
- if (!strncmp(mysqlEncoding, "sjis", 4)) {
- return NSShiftJISStringEncoding;
- }
- if (!strncmp(mysqlEncoding, "big5", 4)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingBig5);
- }
- if (!strncmp(mysqlEncoding, "euc_kr", 6)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR);
- }
- if (!strncmp(mysqlEncoding, "euckr", 5)) {
- return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR);
- }
-
- // Default to iso latin 1, even if it is not exact (throw an exception?)
- NSLog(@"WARNING : unknown name for MySQL encoding '%s'!\n\t\tFalling back to iso-latin1.", mysqlEncoding);
- return NSISOLatin1StringEncoding;
-}
-
-
-/*
- * Modified version of selectDB to be used in Sequel Pro.
- * Checks the connection exists, and handles keepalive, otherwise calling the parent implementation.
- */
-- (BOOL) selectDB:(NSString *) dbName
-{
- if (!mConnected) return NO;
- [self stopKeepAliveTimer];
- if (![self checkConnection]) return NO;
- if ([super selectDB:dbName]) {
- [self startKeepAliveTimerResettingState:YES];
- return YES;
- }
- [self setLastErrorMessage:nil];
- lastQueryErrorId = mysql_errno(mConnection);
- if (connectionTunnel) {
- [connectionTunnel disconnect];
- if (delegate) [delegate setTitlebarStatus:@"SSH Disconnected"];
- //[delegate setStatusIconToImageWithName:@"ssh-disconnected"];
- }
- return NO;
-}
-
-
-/*
- * Via that method the current mySQLConnection will be informed
- * which object sent the current query.
- */
-- (void)willPerformQuery:(NSNotification *)notification
-{
-
- // If the sender was CustomQuery disable the retry of queries.
- // TODO: maybe there's a better way
- if( [[[[notification object] class] description] isEqualToString:@"CustomQuery"] ) {
- retryAllowed = NO;
- } else {
- retryAllowed = YES;
- }
-
-}
-
-/**
- * This method is called as part of Key Value Observing which is used to watch for prefernce changes which effect the interface.
- */
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
- if ([keyPath isEqualToString:@"ConsoleEnableLogging"]) {
- consoleLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"ConsoleEnableLogging"];
- }
-}
-
-/*
- * Override the standard queryString: method to default to the connection encoding, as before,
- * before pssing on to queryString: usingEncoding:.
- */
-- (CMMCPResult *)queryString:(NSString *) query
-{
- return [self queryString:query usingEncoding:mEncoding];
-}
-
-
-/*
- * Modified version of queryString to be used in Sequel Pro.
- * Error checks connection extensively - if this method fails due to a connection error, it will ask how to
- * proceed and loop depending on the status, not returning control until either the query has been executed
- * and the result can be returned or the connection and document have been closed.
- */
-- (CMMCPResult *)queryString:(NSString *) query usingEncoding:(NSStringEncoding) encoding
-{
- CMMCPResult *theResult = nil;
- uint64_t queryStartTime, queryExecutionTime_t;
- Nanoseconds queryExecutionTime;
- const char *theCQuery;
- unsigned long theCQueryLength;
- int queryResultCode;
- int queryErrorId = 0;
- my_ulonglong queryAffectedRows = 0;
- int currentMaxAllowedPacket = -1;
- BOOL isQueryRetry = NO;
- NSString *queryErrorMessage = nil;
-
- // If no connection is present, return nil.
- if (!mConnected) {
- // Write a log entry
- if ([delegate respondsToSelector:@selector(queryGaveError:)]) [delegate queryGaveError:@"No connection available!"];
- // Notify that the query has been performed
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
- // Show an error alert while resetting
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), @"No connection available!",
- nil, nil, [delegate valueForKeyPath:@"tableWindow"], self, nil, nil, nil, @"No connection available!");
- return nil;
- }
-
- (void)(*stopKeepAliveTimerPtr)(self, stopKeepAliveTimerSEL);
-
- // queryStartTime = clock();
-
- // Inform the delegate about the query if logging is enabled and
- // delegate responds to willQueryString:
- if (consoleLoggingEnabled && delegateResponseToWillQueryString)
- (void)(NSString*)(*willQueryStringPtr)(delegate, willQueryStringSEL, query);
-
- // Derive the query string in the correct encoding
- NSData *d = NSStringDataUsingLossyEncoding(query, encoding, 1);
- theCQuery = [d bytes];
- // Set the length of the current query
- theCQueryLength = [d length];
-
- // Check query length against max_allowed_packet; if it is larger, the
- // query would error, so if max_allowed_packet is editable for the user
- // increase it for the current session and reconnect.
- if(maxAllowedPacketSize < theCQueryLength) {
-
- if(isMaxAllowedPacketEditable) {
-
- currentMaxAllowedPacket = maxAllowedPacketSize;
- [self setMaxAllowedPacketTo:strlen(theCQuery)+1024 resetSize:NO];
- [self reconnect];
-
- } else {
-
- NSString *errorMessage = [NSString stringWithFormat:NSLocalizedString(@"The query length of %d bytes is larger than max_allowed_packet size (%d).",
- @"error message if max_allowed_packet < query size"),
- theCQueryLength, maxAllowedPacketSize];
-
- // Write a log entry and update the connection error messages for those uses that check it
- if ([delegate respondsToSelector:@selector(queryGaveError:)]) [delegate queryGaveError:errorMessage];
- [self setLastErrorMessage:errorMessage];
-
- // Notify that the query has been performed
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
- // Show an error alert while resetting
- NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
- nil, nil, [delegate valueForKeyPath:@"tableWindow"], self, nil, nil, nil, errorMessage);
-
- return nil;
- }
- }
-
- // In a loop to allow one reattempt, perform the query.
- while (1) {
-
- // If this query has failed once already, check the connection
- if (isQueryRetry) {
- if (![self checkConnection]) {
-
- // Notify that the query has been performed
- [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self];
- return nil;
- }
- }
-
- // Run (or re-run) the query, timing the execution time of the query - note
- // that this time will include network lag.
- queryStartTime = mach_absolute_time();
- queryResultCode = mysql_real_query(mConnection, theCQuery, theCQueryLength);
- queryExecutionTime_t = mach_absolute_time() - queryStartTime;
- queryExecutionTime = AbsoluteToNanoseconds( *(AbsoluteTime *) &(queryExecutionTime_t) );
-
- // On success, capture the results
- if (0 == queryResultCode) {
-
- if (mysql_field_count(mConnection) != 0) {
- theResult = [[CMMCPResult alloc] initWithMySQLPtr:mConnection encoding:mEncoding timeZone:mTimeZone];
-
- // Ensure no problem occurred during the result fetch
- if (mysql_errno(mConnection) != 0) {
- queryErrorMessage = [[NSString alloc] initWithString:[self stringWithCString:mysql_error(mConnection)]];
- queryErrorId = mysql_errno(mConnection);
- break;
- }
- }
-
- queryErrorMessage = [[NSString alloc] initWithString:@""];
- queryErrorId = 0;
- queryAffectedRows = mysql_affected_rows(mConnection);
-
- // On failure, set the error messages and IDs
- } else {
-
- queryErrorMessage = [[NSString alloc] initWithString:[self stringWithCString:mysql_error(mConnection)]];
- queryErrorId = mysql_errno(mConnection);
-
- // If the error was a connection error, retry once
- if (!isQueryRetry && retryAllowed && [CMMCPConnection isErrorNumberConnectionError:queryErrorId]) {
- isQueryRetry = YES;
- continue;
- }
- }
-
- break;
- }
-
- // If the mysql thread id has changed as a result of a connection error,
- // ensure connection details are still correct
- if (connectionThreadId != mConnection->thread_id) [self restoreConnectionDetails];
-
- // If max_allowed_packet was changed, reset it to default
- if(currentMaxAllowedPacket > -1)
- [self setMaxAllowedPacketTo:currentMaxAllowedPacket resetSize:YES];
-
- // Update error strings and IDs
- lastQueryErrorId = queryErrorId;
- [self setLastErrorMessage:queryErrorMessage?queryErrorMessage:@""];
- if (queryErrorMessage) [queryErrorMessage release];
- lastQueryAffectedRows = queryAffectedRows;
- lastQueryExecutionTime = ((double) UnsignedWideToUInt64( queryExecutionTime )) * 1e-9;
-
- // If an error occurred, inform the delegate
- if (queryResultCode & delegateResponseToWillQueryString)
- [delegate queryGaveError:lastQueryErrorMessage];
-
- (void)(int)(*startKeepAliveTimerResettingStatePtr)(self, startKeepAliveTimerResettingStateSEL, YES);
-
- if (!theResult) return nil;
- return [theResult autorelease];
-}
-
-
-/*
- * Return the time taken to execute the last query. This should be close to the time it took
- * the server to run the query, but will include network lag and some client library overhead.
- */
-- (double) lastQueryExecutionTime
-{
- return lastQueryExecutionTime;
-}
-
-
-/*
- * Modified version of selectDB to be used in Sequel Pro.
- * Checks the connection exists, and handles keepalive, otherwise calling the parent implementation.
- */
-- (MCPResult *) listDBsLike:(NSString *) dbsName
-{
- if (!mConnected) return NO;
- [self stopKeepAliveTimer];
- if (![self checkConnection]) return [[[MCPResult alloc] init] autorelease];
- [self startKeepAliveTimerResettingState:YES];
- return [super listDBsLike:dbsName];
-}
-
-
-/*
- * Checks whether the connection to the server is still active. If not, prompts for what approach to take,
- * offering to retry, reconnect or disconnect the connection.
- */
-- (BOOL)checkConnection
-{
- if (!mConnected) return NO;
-
- BOOL connectionVerified = FALSE;
-
- // Check whether the connection is still operational via a wrapped version of MySQL ping.
- connectionVerified = [self pingConnection];
-
- // If the connection doesn't appear to be responding, show a dialog asking how to proceed
- if (!connectionVerified) {
- [NSApp beginSheet:connectionErrorDialog modalForWindow:parentWindow modalDelegate:self didEndSelector:nil contextInfo:nil];
- int responseCode = [NSApp runModalForWindow:connectionErrorDialog];
- [NSApp endSheet:connectionErrorDialog];
- [connectionErrorDialog orderOut:nil];
-
- switch (responseCode) {
-
- // "Reconnect" has been selected. Request a reconnect, and retry.
- case 1:
- [self reconnect];
- return [self checkConnection];
-
- // "Disconnect" has been selected. Close the parent window, which will handle disconnections, and return false.
- case 2:
- [parentWindow close];
- return FALSE;
-
- // "Retry" has been selected - return a recursive call.
- default:
- return [self checkConnection];
- }
-
- // If a connection exists, check whether the thread id differs; if so, the connection has
- // probably been reestablished and we need to reset the connection encoding
- } else if (connectionThreadId != mConnection->thread_id) [self restoreConnectionDetails];
-
- return connectionVerified;
-}
-
-/**
- * Restore the connection encoding details as necessary based on the delegate-provided
- * details.
- */
-- (void) restoreConnectionDetails
-{
- connectionThreadId = mConnection->thread_id;
- [self fetchMaxAllowedPacket];
- if (delegate && [delegate valueForKey:@"_encoding"]) {
- [self queryString:[NSString stringWithFormat:@"/*!40101 SET NAMES '%@' */", [NSString stringWithString:[delegate valueForKey:@"_encoding"]]]];
- if (delegate && [delegate respondsToSelector:@selector(connectionEncodingViaLatin1)]) {
- if ([delegate connectionEncodingViaLatin1]) [self queryString:@"/*!40101 SET CHARACTER_SET_RESULTS=latin1 */"];
- }
- }
-}
-
-- (void)setDelegate:(id)object
-{
- delegate = object;
-
- delegateResponseToWillQueryString = (delegate && [delegate respondsToSelector:willQueryStringSEL]);
-
- willQueryStringPtr = [delegate methodForSelector:willQueryStringSEL];
-
-}
-
-/* Getting the currently used time zone (in communication with the DB server). */
-/* fixes mysql 4.1.14 problem, can be deleted as soon as fixed in the framework */
-- (NSTimeZone *)timeZone
-{
- if ([self checkConnection]) {
- MCPResult *theSessionTZ = [self queryString:@"SHOW VARIABLES LIKE '%time_zone'"];
- NSArray *theRow;
- id theTZName;
- NSTimeZone *theTZ;
-
- [theSessionTZ dataSeek:1ULL];
- theRow = [theSessionTZ fetchRowAsArray];
- theTZName = [theRow objectAtIndex:1];
-
- if ( [theTZName isKindOfClass:[NSData class]] ) {
- // MySQL 4.1.14 returns the mysql variables as NSData
- theTZName = [self stringWithText:theTZName];
- }
-
- if ([theTZName isEqualToString:@"SYSTEM"]) {
- [theSessionTZ dataSeek:0ULL];
- theRow = [theSessionTZ fetchRowAsArray];
- theTZName = [theRow objectAtIndex:1];
-
- if ( [theTZName isKindOfClass:[NSData class]] ) {
- // MySQL 4.1.14 returns the mysql variables as NSData
- theTZName = [self stringWithText:theTZName];
- }
- }
-
- if (theTZName) { // Old versions of the server does not support there own time zone ?
- theTZ = [NSTimeZone timeZoneWithName:theTZName];
- } else {
- // By default set the time zone to the local one..
- // Try to get the name using the previously available variable:
- theSessionTZ = [self queryString:@"SHOW VARIABLES LIKE 'timezone'"];
- [theSessionTZ dataSeek:0ULL];
- theRow = [theSessionTZ fetchRowAsArray];
- theTZName = [theRow objectAtIndex:1];
- if (theTZName) {
- // Finally we found one ...
- theTZ = [NSTimeZone timeZoneWithName:theTZName];
- } else {
- theTZ = [NSTimeZone defaultTimeZone];
- //theTZ = [NSTimeZone systemTimeZone];
- NSLog(@"The time zone is not defined on the server, set it to the default one : %@", theTZ);
- }
- }
-
- if (theTZ != mTimeZone) {
- [mTimeZone release];
- mTimeZone = [theTZ retain];
- }
- }
- return mTimeZone;
-}
-
-
-/*
- * The current versions of MCPKit (and up to and including 3.0.1) use MySQL 4.1.12; this has an issue with
- * mysql_ping where a connection which is terminated will cause mysql_ping never to respond, even when
- * connection timeouts are set. Full details of this issue are available at http://bugs.mysql.com/bug.php?id=9678 ;
- * this bug was fixed in 4.1.22 and later versions.
- * This issue can be replicated by connecting to a remote host, and then configuring a firewall on that host
- * to drop all packets on the connected port - mysql_ping and so Sequel Pro will hang.
- * Until the client libraries are updated, this provides a drop-in wrapper for mysql_ping, which calls mysql_ping
- * while running a SIGALRM to enforce the specified connection time. This is low-level but effective.
- * Unlike mysql_ping, this function returns FALSE on failure and TRUE on success.
- */
-- (BOOL) pingConnection
-{
- struct sigaction timeoutAction;
- NSDate *startDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
- BOOL pingSuccess = FALSE;
-
- // Construct the SIGALRM to fire after the connection timeout if it isn't cleared, calling the forcePingTimeout function.
- timeoutAction.sa_handler = forcePingTimeout;
- sigemptyset(&timeoutAction.sa_mask);
- timeoutAction.sa_flags = 0;
- sigaction(SIGALRM, &timeoutAction, NULL);
- alarm(connectionTimeout+1);
-
- // Set up a "restore point", returning 0; if longjmp is used later with this reference, execution
- // jumps back to this point and returns a nonzero value, so this function evaluates to false when initially
- // set and true if it's called again.
- if (setjmp(pingTimeoutJumpLocation)) {
-
- // The connection timed out - we want to return false.
- pingSuccess = FALSE;
-
- // On direct execution:
- } else {
-
- // Run mysql_ping, which returns 0 on success, and otherwise an error.
- pingSuccess = (BOOL)(! mysql_ping(mConnection));
-
- // If the ping failed within a second, try another one; this is because a terminated-but-then
- // restored connection is at times restored or functional after a ping, but the ping still returns
- // an error. This additional check ensures the returned status is correct with minimal other effect.
- if (!pingSuccess && ([startDate timeIntervalSinceNow] > -1)) {
- pingSuccess = (BOOL)(! mysql_ping(mConnection));
- }
- }
-
- // Reset and clear the SIGALRM used to check connection timeouts.
- alarm(0);
- timeoutAction.sa_handler = SIG_IGN;
- sigemptyset(&timeoutAction.sa_mask);
- timeoutAction.sa_flags = 0;
- sigaction(SIGALRM, &timeoutAction, NULL);
-
- [startDate release];
-
- return pingSuccess;
-}
-
-/*
- * This function is paired with pingConnection, and provides a method of enforcing the connection
- * timeout when mysql_ping does not respect the specified limits.
- */
-static void forcePingTimeout(int signalNumber)
-{
- longjmp(pingTimeoutJumpLocation, 1);
-}
-
-/*
- * Restarts a keepalive to fire in the future.
- */
-- (void) startKeepAliveTimerResettingState:(BOOL)resetState
-{
- if (keepAliveTimer) [self stopKeepAliveTimer];
- if (!mConnected) return;
-
- if (resetState && lastKeepAliveSuccess) {
- [lastKeepAliveSuccess release];
- lastKeepAliveSuccess = nil;
- }
-
- if (useKeepAlive && keepAliveInterval) {
- keepAliveTimer = [NSTimer
- scheduledTimerWithTimeInterval:keepAliveInterval
- target:self
- selector:@selector(keepAlive:)
- userInfo:nil
- repeats:NO];
- [keepAliveTimer retain];
- }
-}
-
-/*
- * Stops a keepalive if one is set for the future.
- */
-- (void) stopKeepAliveTimer
-{
- if (!keepAliveTimer) return;
- [keepAliveTimer invalidate];
- [keepAliveTimer release];
- keepAliveTimer = nil;
-}
-
-/*
- * Keeps a connection alive by running a ping.
- */
-- (void) keepAlive:(NSTimer *)theTimer
-{
- if (!mConnected) return;
-
- // If there a successful keepalive record exists, and it was more than 5*keepaliveinterval ago,
- // abort. This prevents endless spawning of threads in a state where the connection has been
- // cut but mysql doesn't pick up on the fact - see comment for pingConnection above. The same
- // forced-timeout approach cannot be used here on a background thread.
- // When the connection is disconnected in code, these 5 "hanging" threads are automatically cleaned.
- if (lastKeepAliveSuccess && [lastKeepAliveSuccess timeIntervalSinceNow] < -5 * keepAliveInterval) return;
-
- [NSThread detachNewThreadSelector:@selector(threadedKeepAlive) toTarget:self withObject:nil];
- [self startKeepAliveTimerResettingState:NO];
-}
-
-/*
- * A threaded keepalive to avoid blocking the interface
- */
-- (void) threadedKeepAlive
-{
- if (!mConnected) return;
- mysql_ping(mConnection);
- if (lastKeepAliveSuccess) {
- [lastKeepAliveSuccess release];
- lastKeepAliveSuccess = nil;
- }
- lastKeepAliveSuccess = [[NSDate alloc] initWithTimeIntervalSinceNow:0];
-}
-
-/*
- * Modified version of the original to support a supplied encoding.
- * For internal use only. Transforms a NSString to a C type string (ending with \0).
- * Lossy conversions are enabled.
- */
-- (const char *) cStringFromString:(NSString *) theString usingEncoding:(NSStringEncoding) encoding
-{
-
- NSMutableData *theData;
-
- if (! theString) {
- return (const char *)NULL;
- }
-
- theData = [NSMutableData dataWithData:[theString dataUsingEncoding:encoding allowLossyConversion:YES]];
- [theData increaseLengthBy:1];
- return (const char *)[theData bytes];
-}
-
-/*
- * Returns a string for the last MySQL error message on the connection.
- * This is cached within the object to allow helper queries to be performed
- * without affecting the state that the GUI is querying.
- */
-- (NSString *) getLastErrorMessage
-{
- return lastQueryErrorMessage;
-}
-
-/*
- * Sets the string for the last MySQL error message on the connection,
- * managing memory as appropriate. Supply a nil string to store the
- * last error on the connection.
- */
-- (void) setLastErrorMessage:(NSString *)theErrorMessage
-{
- if (!theErrorMessage) theErrorMessage = [self stringWithCString:mysql_error(mConnection)];
-
- if (lastQueryErrorMessage) [lastQueryErrorMessage release], lastQueryErrorMessage = nil;
- lastQueryErrorMessage = [[NSString alloc] initWithString:theErrorMessage];
-}
-
-/*
- * Returns the ErrorID of the last MySQL error on the connection.
- * This is cached within the object to allow helper queries to be performed
- * without affecting the state that the GUI is querying.
- */
-- (unsigned int) getLastErrorID
-{
- return lastQueryErrorId;
-}
-
-/*
- * Returns the number of affected rows by the last query.
- * This is cached within the object to allow helper queries to be performed
- * without affecting the state that the GUI is querying.
- */
-- (my_ulonglong) affectedRows
-{
- return lastQueryAffectedRows;
-}
-
-/*
- * Retrieve the max_allowed_packet size from the server; returns
- * false if the query fails.
- */
-- (BOOL) fetchMaxAllowedPacket
-{
- char *queryString;
-
- if ([self serverMajorVersion] == 3) queryString = "SHOW VARIABLES LIKE 'max_allowed_packet'";
- else queryString = "SELECT @@global.max_allowed_packet";
- if (0 == mysql_query(mConnection, queryString)) {
- if (mysql_field_count(mConnection) != 0) {
- CMMCPResult *r = [[CMMCPResult alloc] initWithMySQLPtr:mConnection encoding:mEncoding timeZone:mTimeZone];
- NSArray *a = [r fetchRowAsArray];
- [r autorelease];
- if([a count]) {
- maxAllowedPacketSize = [[a objectAtIndex:([self serverMajorVersion] == 3)?1:0] intValue];
- return true;
- }
- }
- }
-
- return false;
-}
-
-/*
- * Retrieves max_allowed_packet size set as global variable.
- * It returns -1 if it fails.
- */
-- (int) getMaxAllowedPacket
-{
- return maxAllowedPacketSize;
-}
-
-/*
- * It sets max_allowed_packet size to newSize and it returns
- * max_allowed_packet after setting it to newSize for cross-checking
- * if the maximal size was reached (e.g. set it to 4GB it'll return 1GB up to now).
- * If something failed it return -1;
- */
-- (int) setMaxAllowedPacketTo:(int)newSize resetSize:(BOOL)reset
-{
- if(![self isMaxAllowedPacketEditable] || newSize < 1024) return maxAllowedPacketSize;
-
- mysql_query(mConnection, [[NSString stringWithFormat:@"SET GLOBAL max_allowed_packet = %d", newSize] UTF8String]);
- // Inform the user via a log entry about that change according to reset value
- if(delegate && [delegate respondsToSelector:@selector(queryGaveError:)])
- if(reset)
- [delegate queryGaveError:[NSString stringWithFormat:@"max_allowed_packet was reset to %d for new session", newSize]];
- else
- [delegate queryGaveError:[NSString stringWithFormat:@"Query too large; max_allowed_packet temporarily set to %d for the current session to allow query to succeed", newSize]];
-
- return maxAllowedPacketSize;
-}
-
-
-/*
- * It returns whether max_allowed_packet is setable for the user.
- */
-- (BOOL) isMaxAllowedPacketEditable
-{
- return(!mysql_query(mConnection, "SET GLOBAL max_allowed_packet = @@global.max_allowed_packet"));
-}
-
-/*
- * Check some common locations for the presence of a MySQL socket file, returning
- * it if successful.
- */
-- (NSString *)findSocketPath
-{
- NSFileManager *fileManager = [NSFileManager defaultManager];
- NSArray *possibleSocketLocations = [NSArray arrayWithObjects:
- @"/tmp/mysql.sock", // Default
- @"/var/run/mysqld/mysqld.sock", // As used on Debian/Gentoo
- @"/var/tmp/mysql.sock", // As used on FreeBSD
- @"/var/lib/mysql/mysql.sock", // As used by Fedora
- @"/opt/local/lib/mysql/mysql.sock", // Alternate fedora
- @"/opt/local/var/run/mysqld/mysqld.sock", // Darwinports MySQL
- @"/opt/local/var/run/mysql4/mysqld.sock", // Darwinports MySQL 4
- @"/opt/local/var/run/mysql5/mysqld.sock", // Darwinports MySQL 5
- @"/Applications/MAMP/tmp/mysql/mysql.sock", // MAMP default location
- nil];
-
- for (int i = 0; i < [possibleSocketLocations count]; i++) {
- if ([fileManager fileExistsAtPath:[possibleSocketLocations objectAtIndex:i]])
- return [possibleSocketLocations objectAtIndex:i];
- }
-
- return nil;
-}
-
-- (void) dealloc
-{
- delegate = nil;
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- if (lastQueryErrorMessage) [lastQueryErrorMessage release];
- if (connectionHost) [connectionHost release];
- if (connectionLogin) [connectionLogin release];
- if (connectionSocket) [connectionSocket release];
- if (connectionPassword) [connectionPassword release];
- if (connectionKeychainName) [connectionKeychainName release];
- if (connectionKeychainAccount) [connectionKeychainAccount release];
- if (lastKeepAliveSuccess) [lastKeepAliveSuccess release];
-
- [super dealloc];
-}
-
-@end \ No newline at end of file