diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPConnectionDelegate.m | 9 | ||||
-rw-r--r-- | Source/SPCopyTable.m | 6 | ||||
-rw-r--r-- | Source/SPCustomQuery.m | 8 | ||||
-rw-r--r-- | Source/SPDataImport.m | 6 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.h | 4 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 107 | ||||
-rw-r--r-- | Source/SPExportController.h | 4 | ||||
-rw-r--r-- | Source/SPExportFileUtilities.m | 2 | ||||
-rw-r--r-- | Source/SPExportInitializer.m | 10 | ||||
-rw-r--r-- | Source/SPExtendedTableInfo.m | 6 | ||||
-rw-r--r-- | Source/SPTableContent.m | 27 | ||||
-rw-r--r-- | Source/SPTableData.m | 63 | ||||
-rw-r--r-- | Source/SPTablesList.m | 47 | ||||
-rw-r--r-- | Source/SPXMLExporterDelegate.m | 4 |
14 files changed, 171 insertions, 132 deletions
diff --git a/Source/SPConnectionDelegate.m b/Source/SPConnectionDelegate.m index 5231c996..b1e586f1 100644 --- a/Source/SPConnectionDelegate.m +++ b/Source/SPConnectionDelegate.m @@ -70,15 +70,6 @@ } /** - * Invoked when the framework is in the process of reconnecting to the server and needs to know - * what encoding to use for the connection. - */ -- (NSString *)onReconnectShouldUseEncoding:(id)connection -{ - return _encoding; -} - -/** * Invoked when the current connection needs a password from the Keychain. */ - (NSString *)keychainPasswordForConnection:(MCPConnection *)connection diff --git a/Source/SPCopyTable.m b/Source/SPCopyTable.m index b1b663a4..db8ce49d 100644 --- a/Source/SPCopyTable.m +++ b/Source/SPCopyTable.m @@ -295,7 +295,7 @@ NSInteger MENU_EDIT_COPY_AS_SQL = 2003; else if ([cellData isSPNotLoaded]) [result appendFormat:@"%@\t", NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields")]; else if ([cellData isKindOfClass:[NSData class]]) { - NSString *displayString = [[NSString alloc] initWithData:cellData encoding:connectionEncoding]; + NSString *displayString = [[NSString alloc] initWithData:cellData encoding:[mySQLConnection stringEncoding]]; if (!displayString) displayString = [[NSString alloc] initWithData:cellData encoding:NSASCIIStringEncoding]; if (displayString) { [result appendFormat:@"%@\t", displayString]; @@ -520,7 +520,7 @@ NSInteger MENU_EDIT_COPY_AS_SQL = 2003; NSUInteger rowIndex = [selectedRows firstIndex]; NSString *nullString = [prefs objectForKey:SPNullValue]; Class nsDataClass = [NSData class]; - NSStringEncoding connectionEncoding = [mySQLConnection encoding]; + NSStringEncoding connectionEncoding = [mySQLConnection stringEncoding]; while ( rowIndex != NSNotFound ) { for ( c = 0; c < numColumns; c++) { @@ -681,7 +681,7 @@ NSInteger MENU_EDIT_COPY_AS_SQL = 2003; // Otherwise, ensure the cell is represented as a short string if ([contentString isKindOfClass:[NSData class]]) { - contentString = [contentString shortStringRepresentationUsingEncoding:[mySQLConnection encoding]]; + contentString = [contentString shortStringRepresentationUsingEncoding:[mySQLConnection stringEncoding]]; } else if ([contentString length] > 500) { contentString = [contentString substringToIndex:500]; } diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m index 82b40465..adb806ad 100644 --- a/Source/SPCustomQuery.m +++ b/Source/SPCustomQuery.m @@ -1792,7 +1792,7 @@ } if ([theValue isKindOfClass:[NSData class]]) - return [theValue shortStringRepresentationUsingEncoding:[mySQLConnection encoding]]; + return [theValue shortStringRepresentationUsingEncoding:[mySQLConnection stringEncoding]]; if ([theValue isNSNull]) return [prefs objectForKey:SPNullValue]; @@ -2262,9 +2262,9 @@ id editData = [[fieldEditor editWithObject:originalData fieldName:[columnDefinition objectForKey:@"name"] - usingEncoding:[mySQLConnection encoding] - isObjectBlob:isBlob - isEditable:isFieldEditable + usingEncoding:[mySQLConnection stringEncoding] + isObjectBlob:isBlob + isEditable:isFieldEditable withWindow:[tableDocumentInstance parentWindow]] retain]; if ( editData ) diff --git a/Source/SPDataImport.m b/Source/SPDataImport.m index ac1eadc0..98129f19 100644 --- a/Source/SPDataImport.m +++ b/Source/SPDataImport.m @@ -233,7 +233,7 @@ if ([[[importFormatPopup selectedItem] title] isEqualToString:@"SQL"]) encoding = NSUTF8StringEncoding; else - encoding = [MCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]; + encoding = [mySQLConnection stringEncoding]; if(![[[NSPasteboard generalPasteboard] stringForType:NSStringPboardType] writeToFile:importFileName atomically:NO encoding:encoding error:nil]) { NSBeep(); @@ -406,7 +406,7 @@ sqlEncoding = [fileEncodingDetector encoding]; [fileEncodingDetector release]; if ([MCPConnection mySQLEncodingForStringEncoding:sqlEncoding]) { - connectionEncodingToRestore = [tableDocumentInstance connectionEncoding]; + connectionEncodingToRestore = [mySQLConnection encoding]; [mySQLConnection queryString:[NSString stringWithFormat:@"SET NAMES '%@'", [MCPConnection mySQLEncodingForStringEncoding:sqlEncoding]]]; } } @@ -673,7 +673,7 @@ BOOL allDataRead = NO; BOOL insertBaseStringHasEntries; - NSStringEncoding csvEncoding = [MCPConnection encodingForMySQLEncoding:[[tableDocumentInstance connectionEncoding] UTF8String]]; + NSStringEncoding csvEncoding = [mySQLConnection stringEncoding]; fieldMappingArray = nil; fieldMappingGlobalValueArray = nil; diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index 28ee97ad..07c3f7bb 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -139,8 +139,6 @@ NSMenu *selectEncodingMenu; BOOL _supportsEncoding; - NSString *_encoding; - BOOL _encodingViaLatin1; BOOL _isConnected; NSInteger _isWorkingLevel; BOOL _mainNibLoaded; @@ -238,8 +236,6 @@ // Encoding methods - (void)setConnectionEncoding:(NSString *)mysqlEncoding reloadingViews:(BOOL)reloadViews; - (NSString *)databaseEncoding; -- (NSString *)connectionEncoding; -- (BOOL)connectionEncodingViaLatin1:(id)connection; - (IBAction)chooseEncoding:(id)sender; - (BOOL)supportsEncoding; - (void)updateEncodingMenuWithSelectedEncoding:(NSNumber *)encodingTag; diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index e99bc702..00831c85 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -83,7 +83,6 @@ if ((self = [super init])) { _mainNibLoaded = NO; - _encoding = [[NSString alloc] initWithString:@"utf8"]; _isConnected = NO; _isWorkingLevel = 0; _isSavedInBundle = NO; @@ -552,7 +551,7 @@ [mainToolbar setVisible:[[spfSession objectForKey:@"isToolbarVisible"] boolValue]]; // Reset database view encoding if differs from default - if([spfSession objectForKey:@"connectionEncoding"] && ![[self connectionEncoding] isEqualToString:[spfSession objectForKey:@"connectionEncoding"]]) + if([spfSession objectForKey:@"connectionEncoding"] && ![[mySQLConnection encoding] isEqualToString:[spfSession objectForKey:@"connectionEncoding"]]) [self setConnectionEncoding:[spfSession objectForKey:@"connectionEncoding"] reloadingViews:YES]; if(isSelectedTableDefined) { @@ -658,14 +657,6 @@ // ...but hide the icon while the document is temporary if ([self isUntitled]) [[parentWindow standardWindowButton:NSWindowDocumentIconButton] setImage:nil]; - // Set the connection encoding - NSNumber *encodingType = [prefs objectForKey:SPDefaultEncoding]; - if ( [encodingType intValue] == SPEncodingAutodetect ) { - [self setConnectionEncoding:[self databaseEncoding] reloadingViews:NO]; - } else { - [self setConnectionEncoding:[self mysqlEncodingFromEncodingTag:encodingType] reloadingViews:NO]; - } - // Get the mysql version mySQLVersion = [[NSString alloc] initWithString:[mySQLConnection serverVersionString]]; @@ -676,12 +667,24 @@ [spHistoryControllerInstance updateHistoryEntries]; } + // Ensure the connection encoding is set to utf8 for database/table name retrieval + [mySQLConnection setEncoding:@"utf8"]; + // Update the database list [self setDatabases:self]; [chooseDatabaseButton setEnabled:!_isWorkingLevel]; - // For each of the main controllers, assign the current connection + // Set the connection on the tables list instance - this updates the table list while the connection + // is still UTF8 [tablesListInstance setConnection:mySQLConnection]; + + // Set the connection encoding if necessary + NSNumber *encodingType = [prefs objectForKey:SPDefaultEncoding]; + if ( [encodingType intValue] != SPEncodingAutodetect ) { + [self setConnectionEncoding:[self mysqlEncodingFromEncodingTag:encodingType] reloadingViews:NO]; + } + + // For each of the main controllers, assign the current connection [tableSourceInstance setConnection:mySQLConnection]; [tableContentInstance setConnection:mySQLConnection]; [tableRelationsInstance setConnection:mySQLConnection]; @@ -692,9 +695,8 @@ [tableDataInstance setConnection:mySQLConnection]; [extendedTableInfoInstance setConnection:mySQLConnection]; [databaseDataInstance setConnection:mySQLConnection]; -// userManagerInstance.mySqlConnection = mySQLConnection; - // Set the cutom query editor's MySQL version + // Set the custom query editor's MySQL version [customQueryInstance setMySQLversion:mySQLVersion]; [self updateWindowTitle:self]; @@ -1561,41 +1563,32 @@ */ - (void)setConnectionEncoding:(NSString *)mysqlEncoding reloadingViews:(BOOL)reloadViews { - _encodingViaLatin1 = NO; + BOOL useLatin1Transport = NO; // Special-case UTF-8 over latin 1 to allow viewing/editing of mangled data. if ([mysqlEncoding isEqualToString:@"utf8-"]) { - _encodingViaLatin1 = YES; + useLatin1Transport = YES; mysqlEncoding = @"utf8"; } - // set encoding of connection and client - [mySQLConnection queryString:[NSString stringWithFormat:@"SET NAMES '%@'", mysqlEncoding]]; - - if (![mySQLConnection queryErrored]) { - if (_encodingViaLatin1) - [mySQLConnection queryString:@"SET CHARACTER_SET_RESULTS=latin1"]; - [mySQLConnection setEncoding:[MCPConnection encodingForMySQLEncoding:[mysqlEncoding UTF8String]]]; - [_encoding release]; - _encoding = [[NSString alloc] initWithString:mysqlEncoding]; - } else { - [mySQLConnection queryString:[NSString stringWithFormat:@"SET NAMES '%@'", [self databaseEncoding]]]; - _encodingViaLatin1 = NO; - if ([mySQLConnection queryErrored]) { - NSLog(@"Error: could not set encoding to %@ nor fall back to database encoding on MySQL %@", mysqlEncoding, [self mySQLVersion]); - return; - } + // Set the connection encoding + if (![mySQLConnection setEncoding:mysqlEncoding]) { + NSLog(@"Error: could not set encoding to %@ nor fall back to database encoding on MySQL %@", mysqlEncoding, [self mySQLVersion]); + return; } + [mySQLConnection setEncodingUsesLatin1Transport:useLatin1Transport]; - // update the selected menu item - if (_encodingViaLatin1) { + // Update the selected menu item + if (useLatin1Transport) { [self updateEncodingMenuWithSelectedEncoding:[self encodingTagFromMySQLEncoding:[NSString stringWithFormat:@"%@-", mysqlEncoding]]]; } else { [self updateEncodingMenuWithSelectedEncoding:[self encodingTagFromMySQLEncoding:mysqlEncoding]]; } + // Update the stored connection encoding to prevent switches + [mySQLConnection storeEncodingForRestoration]; + // Reload stuff as appropriate - [tableDataInstance resetAllData]; if (reloadViews) { if ([tablesListInstance structureLoaded]) [tableSourceInstance reloadTable:self]; if ([tablesListInstance contentLoaded]) [tableContentInstance reloadTable:self]; @@ -1604,23 +1597,6 @@ } /** - * returns the current mysql encoding for this object - */ -- (NSString *)connectionEncoding -{ - return _encoding; -} - -/** - * Returns whether the current encoding should display results via Latin1 transport for backwards compatibility. - * This is a delegate method of MCPKit's MCPConnection class. - */ -- (BOOL)connectionEncodingViaLatin1:(id)connection -{ - return _encodingViaLatin1; -} - -/** * updates the currently selected item in the encoding menu * * @param NSString *encoding - the title of the menu item which will be selected @@ -1707,26 +1683,29 @@ } /** - * Detect and return the database connection encoding. - * TODO: See http://code.google.com/p/sequel-pro/issues/detail?id=134 - some question over why this [historically] uses _connection not _database... + * Detect and return the database encoding. + * Falls back to Latin1. */ - (NSString *)databaseEncoding { MCPResult *charSetResult; - NSString *mysqlEncoding; + NSString *mysqlEncoding = nil; - // MySQL > 4.0 - charSetResult = [mySQLConnection queryString:@"SHOW VARIABLES LIKE 'character_set_connection'"]; - [charSetResult setReturnDataAsStrings:YES]; - mysqlEncoding = [[charSetResult fetchRowAsDictionary] objectForKey:@"Value"]; - _supportsEncoding = (mysqlEncoding != nil); + // MySQL >= 4.1 + if ([mySQLConnection serverMajorVersion] > 4 + || ([mySQLConnection serverMajorVersion] == 4 && [mySQLConnection serverMinorVersion] >= 1)) + { + charSetResult = [mySQLConnection queryString:@"SHOW VARIABLES LIKE 'character_set_database'"]; + [charSetResult setReturnDataAsStrings:YES]; + mysqlEncoding = [[charSetResult fetchRowAsDictionary] objectForKey:@"Value"]; + _supportsEncoding = (mysqlEncoding != nil); // mysql 4.0 or older -> only default character set possible, cannot choose others using "set names xy" - if ( !mysqlEncoding ) { + } else { mysqlEncoding = [[[mySQLConnection queryString:@"SHOW VARIABLES LIKE 'character_set'"] fetchRowAsDictionary] objectForKey:@"Value"]; } - // older version? -> set encoding to mysql default encoding latin1 + // Fallback or older version? -> set encoding to mysql default encoding latin1 if ( !mysqlEncoding ) { NSLog(@"Error: no character encoding found, mysql version is %@", [self mySQLVersion]); mysqlEncoding = @"latin1"; @@ -3380,7 +3359,7 @@ [session setObject:aString forKey:@"view"]; [session setObject:[NSNumber numberWithBool:[[parentWindow toolbar] isVisible]] forKey:@"isToolbarVisible"]; - [session setObject:[self connectionEncoding] forKey:@"connectionEncoding"]; + [session setObject:[mySQLConnection encoding] forKey:@"connectionEncoding"]; [session setObject:[NSNumber numberWithBool:[tableContentInstance sortColumnIsAscending]] forKey:@"contentSortColIsAsc"]; [session setObject:[NSNumber numberWithInteger:[tableContentInstance pageNumber]] forKey:@"contentPageNumber"]; @@ -4675,7 +4654,6 @@ for (id retainedObject in nibObjectsToRelease) [retainedObject release]; [nibObjectsToRelease release]; - [_encoding release]; [allDatabases release]; [allSystemDatabases release]; [printWebView release]; @@ -4773,6 +4751,9 @@ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, parentWindow, self, nil, nil, NSLocalizedString(@"Database must have a name.", @"message of panel when no db name is given")); return; } + + // As we're amending identifiers, ensure UTF8 + if (![[mySQLConnection encoding] isEqualToString:@"utf8"]) [mySQLConnection setEncoding:@"utf8"]; NSString *createStatement = [NSString stringWithFormat:@"CREATE DATABASE %@", [[databaseNameField stringValue] backtickQuotedString]]; diff --git a/Source/SPExportController.h b/Source/SPExportController.h index c5dade4a..befde1b9 100644 --- a/Source/SPExportController.h +++ b/Source/SPExportController.h @@ -198,12 +198,12 @@ * User defaults */ NSUserDefaults *prefs; - + /** * Previous connection encoding */ NSString *sqlPreviousConnectionEncoding; - + /** * Previous connection encoding was via Latin1 */ diff --git a/Source/SPExportFileUtilities.m b/Source/SPExportFileUtilities.m index 74e992e4..23eb7666 100644 --- a/Source/SPExportFileUtilities.m +++ b/Source/SPExportFileUtilities.m @@ -65,7 +65,7 @@ NSLocalizedString(@"Table", @"csv export table heading"), [[tables objectAtIndex:0] objectAtIndex:0], lineEnding, - lineEnding] dataUsingEncoding:[connection encoding]]]; + lineEnding] dataUsingEncoding:[connection stringEncoding]]]; } /** diff --git a/Source/SPExportInitializer.m b/Source/SPExportInitializer.m index cc9aa16e..a34f729b 100644 --- a/Source/SPExportInitializer.m +++ b/Source/SPExportInitializer.m @@ -269,8 +269,8 @@ [sqlExporter setSqlInsertDivider:[exportSQLInsertDividerPopUpButton indexOfSelectedItem]]; // Cache the current connection encoding then change it to UTF-8 to allow SQL dumps to work - sqlPreviousConnectionEncoding = [[NSString alloc] initWithString:[tableDocumentInstance connectionEncoding]]; - sqlPreviousConnectionEncodingViaLatin1 = [tableDocumentInstance connectionEncodingViaLatin1:nil]; + sqlPreviousConnectionEncoding = [[NSString alloc] initWithString:[connection encoding]]; + sqlPreviousConnectionEncodingViaLatin1 = [connection encodingUsesLatin1Transport]; [tableDocumentInstance setConnectionEncoding:@"utf8" reloadingViews:NO]; @@ -354,8 +354,8 @@ [dotExporter setDotDatabaseVersion:[tableDocumentInstance mySQLVersion]]; // Cache the current connection encoding then change it to UTF-8 to allow SQL dumps to work - sqlPreviousConnectionEncoding = [[NSString alloc] initWithString:[tableDocumentInstance connectionEncoding]]; - sqlPreviousConnectionEncodingViaLatin1 = [tableDocumentInstance connectionEncodingViaLatin1:nil]; + sqlPreviousConnectionEncoding = [[NSString alloc] initWithString:[connection encoding]]; + sqlPreviousConnectionEncodingViaLatin1 = [connection encodingUsesLatin1Transport]; [tableDocumentInstance setConnectionEncoding:@"utf8" reloadingViews:NO]; @@ -386,7 +386,7 @@ for (SPExporter *exporter in exporters) { [exporter setConnection:connection]; - [exporter setExportOutputEncoding:[connection encoding]]; + [exporter setExportOutputEncoding:[connection stringEncoding]]; [exporter setExportMaxProgress:(NSInteger)[exportProgressIndicator bounds].size.width]; [exporter setExportUsingLowMemoryBlockingStreaming:[exportProcessLowMemoryButton state]]; [exporter setExportOutputCompressionFormat:[exportOutputCompressionFormatPopupButton indexOfSelectedItem]]; diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m index aac89bb9..f9e0bdb8 100644 --- a/Source/SPExtendedTableInfo.m +++ b/Source/SPExtendedTableInfo.m @@ -348,9 +348,11 @@ [tableSizeFree setStringValue:[self _formatValueWithKey:@"Data_free" inDictionary:statusFields]]; // Set comments + NSString *commentText = [statusFields objectForKey:@"Comment"]; + if (!commentText) commentText = @""; [tableCommentsTextView setEditable:YES]; - [tableCommentsTextView shouldChangeTextInRange:NSMakeRange(0, [[tableCommentsTextView string] length]) replacementString:[statusFields objectForKey:@"Comment"]]; - [tableCommentsTextView setString:[statusFields objectForKey:@"Comment"]]; + [tableCommentsTextView shouldChangeTextInRange:NSMakeRange(0, [[tableCommentsTextView string] length]) replacementString:commentText]; + [tableCommentsTextView setString:commentText]; [tableCommentsTextView didChangeText]; [tableCommentsTextView setEditable:enableInteraction]; diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m index 86a960e5..14150607 100644 --- a/Source/SPTableContent.m +++ b/Source/SPTableContent.m @@ -2342,24 +2342,7 @@ [queryString appendFormat:@" WHERE %@", [self argumentForRow:-2]]; } - // If UTF-8 via Latin1 view encoding is set convert the queryString into Latin1 and - // set the MySQL connection to Latin1 before executing this query to allow editing. - // After executing reset all. - if([tableDocumentInstance connectionEncodingViaLatin1:mySQLConnection]) { - - NSStringEncoding currentEncoding = [mySQLConnection encoding]; - NSString *latin1String = [[NSString alloc] initWithCString:[queryString UTF8String] encoding:NSISOLatin1StringEncoding]; - [mySQLConnection setEncoding:NSISOLatin1StringEncoding]; - [mySQLConnection queryString:@"SET NAMES 'latin1'"]; - [mySQLConnection queryString:latin1String]; - [mySQLConnection setEncoding:currentEncoding]; - [mySQLConnection queryString:@"SET NAMES 'utf8'"]; - [mySQLConnection queryString:@"SET CHARACTER_SET_RESULTS=latin1"]; - [latin1String release]; - - } else { - [mySQLConnection queryString:queryString]; - } + [mySQLConnection queryString:queryString]; [fieldValues release]; [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance]; @@ -3072,7 +3055,7 @@ return [prefs objectForKey:SPNullValue]; if ([theValue isKindOfClass:[NSData class]]) - return [theValue shortStringRepresentationUsingEncoding:[mySQLConnection encoding]]; + return [theValue shortStringRepresentationUsingEncoding:[mySQLConnection stringEncoding]]; if ([theValue isSPNotLoaded]) return NSLocalizedString(@"(not loaded)", @"value shown for hidden blob and text fields"); @@ -3534,9 +3517,9 @@ id editData = [[fieldEditor editWithObject:cellValue fieldName:[[aTableColumn headerCell] stringValue] - usingEncoding:[mySQLConnection encoding] - isObjectBlob:isBlob - isEditable:isFieldEditable + usingEncoding:[mySQLConnection stringEncoding] + isObjectBlob:isBlob + isEditable:isFieldEditable withWindow:[tableDocumentInstance parentWindow]] retain]; if (editData) { diff --git a/Source/SPTableData.m b/Source/SPTableData.m index 8ec18cae..a6a5819a 100644 --- a/Source/SPTableData.m +++ b/Source/SPTableData.m @@ -337,6 +337,7 @@ NSString *encodingString = nil; NSUInteger i, stringStart; unichar quoteCharacter; + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; [columns removeAllObjects]; [columnNames removeAllObjects]; @@ -345,6 +346,12 @@ // Catch unselected tables and return nil if ([tableName isEqualToString:@""] || !tableName) return nil; + // Ensure the encoding is set to UTF8 + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + // Retrieve the CREATE TABLE syntax for the table MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE TABLE %@", [tableName backtickQuotedString]]]; [theResult setReturnDataAsStrings:YES]; @@ -361,6 +368,7 @@ [[tableListInstance valueForKeyPath:@"tablesListView"] deselectAll:nil]; [tableListInstance updateTables:self]; } + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; } return nil; @@ -384,6 +392,7 @@ informativeTextWithFormat:NSLocalizedString(@"The creation syntax could not be retrieved due to a permissions error.\n\nPlease check your user permissions with an administrator.", @"Create syntax permission denied detail")] beginSheetModalForWindow:[NSApp mainWindow] modalDelegate:self didEndSelector:NULL contextInfo:NULL]; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; return nil; } @@ -637,6 +646,8 @@ [encodingString release]; [tableColumns release]; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + return tableData; } @@ -689,10 +700,17 @@ NSDictionary *resultRow; NSMutableDictionary *tableColumn, *viewData; NSUInteger i; + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; // Catch unselected views and return nil if ([viewName isEqualToString:@""] || !viewName) return nil; + // Ensure that queries are made in UTF8 + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + // Retrieve the CREATE TABLE syntax for the table MCPResult *theResult = [mySQLConnection queryString: [NSString stringWithFormat: @"SHOW CREATE TABLE %@", [viewName backtickQuotedString] @@ -706,6 +724,7 @@ nil, nil, [NSApp mainWindow], self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"), [mySQLConnection getLastErrorMessage]]); + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; } return nil; } @@ -722,6 +741,7 @@ informativeTextWithFormat:NSLocalizedString(@"The creation syntax could not be retrieved due to a permissions error.\n\nPlease check your user permissions with an administrator.", @"Create syntax permission denied detail")] beginSheetModalForWindow:[NSApp mainWindow] modalDelegate:self didEndSelector:NULL contextInfo:NULL]; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; return nil; } @@ -738,6 +758,7 @@ nil, nil, [NSApp mainWindow], self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"), [mySQLConnection getLastErrorMessage]]); + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; } return nil; } @@ -787,6 +808,8 @@ [tableColumns release]; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + return viewData; } @@ -797,6 +820,7 @@ */ - (BOOL)updateStatusInformationForCurrentTable { + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; // Catch unselected tables and return false if ([[tableListInstance tableName] isEqualToString:@""] || ![tableListInstance tableName]) @@ -809,6 +833,12 @@ return TRUE; } + // Ensure queries are run as UTF8 + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + // Run the status query and retrieve as a dictionary. NSMutableString *escapedTableName = [NSMutableString stringWithString:[tableListInstance tableName]]; [escapedTableName replaceOccurrencesOfString:@"'" withString:@"\\\'" options:0 range:NSMakeRange(0, [escapedTableName length])]; @@ -837,6 +867,7 @@ nil, nil, [NSApp mainWindow], self, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"An error occured while retrieving status data.\nMySQL said: %@", @"message of panel when retrieving view information failed"), [mySQLConnection getLastErrorMessage]]); + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; } return FALSE; } @@ -854,6 +885,7 @@ // If the "Engine" key is NULL, a problem occurred when retrieving the table information. if ([[status objectForKey:@"Engine"] isNSNull]) { [status setDictionary:[NSDictionary dictionaryWithObjectsAndKeys:@"Error", @"Engine", [NSString stringWithFormat:NSLocalizedString(@"An error occurred retrieving table information. MySQL said: %@", @"MySQL table info retrieval error message"), [status objectForKey:@"Comment"]], @"Comment", [tableListInstance tableName], @"Name", nil]]; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; return FALSE; } @@ -874,6 +906,8 @@ } } + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + return TRUE; } @@ -882,6 +916,14 @@ */ - (BOOL) updateTriggersForCurrentTable { + + // Ensure queries are made in UTF8 + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */", [[tableListInstance tableName] tickQuotedString]]]; [theResult setReturnDataAsStrings:YES]; @@ -894,6 +936,7 @@ [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving the trigger information for table '%@'. Please try again.\n\nMySQL said: %@", @"error retrieving table information informative message"), [tableListInstance tableName], [mySQLConnection getLastErrorMessage]]); if (triggers) [triggers release], triggers = nil; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; } return NO; @@ -905,6 +948,8 @@ [triggers addObject:[theResult fetchRowAsDictionary]]; } + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + return YES; } @@ -1109,6 +1154,13 @@ - (NSArray *)primaryKeyColumnNames { + // Ensure that identifier queries occur over UTF8 + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + NSString *selectedTable = [tableListInstance tableName]; if(![selectedTable length]) return nil; @@ -1122,11 +1174,16 @@ r = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@ /*!50003 WHERE `key` = 'PRI'*/", [selectedTable backtickQuotedString]]]; [r setReturnDataAsStrings:YES]; - if([r numOfRows] < 1) return nil; + if([r numOfRows] < 1) { + if (changeEncoding && [mySQLConnection isConnected]) [mySQLConnection restoreStoredEncoding]; + return nil; + } if ([mySQLConnection queryErrored]) { - if ([mySQLConnection isConnected]) + if ([mySQLConnection isConnected]) { NSRunAlertPanel(@"Error", [NSString stringWithFormat:NSLocalizedString(@"An error occured while retrieving the PRIMARY KEY data:\n\n%@",@"message when the query that fetches the primary keys fails"), [mySQLConnection getLastErrorMessage]], @"OK", nil, nil); + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + } return nil; } @@ -1139,6 +1196,8 @@ } } + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + if([keyColumns count]) return keyColumns; return nil; diff --git a/Source/SPTablesList.m b/Source/SPTablesList.m index 7ae16742..b0e4594e 100644 --- a/Source/SPTablesList.m +++ b/Source/SPTablesList.m @@ -70,6 +70,7 @@ NSInteger i; NSString *previousSelectedTable = nil; BOOL previousTableListIsSelectable = tableListIsSelectable; + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; if (selectedTableName) previousSelectedTable = [[NSString alloc] initWithString:selectedTableName]; if (isTableListFiltered) { @@ -92,6 +93,12 @@ // Notify listeners that a query has started [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance]; + // Use UTF8 for identifier-based queries + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } + // Select the table list for the current database. On MySQL versions after 5 this will include // views; on MySQL versions >= 5.0.02 select the "full" list to also select the table type column. theResult = [mySQLConnection queryString:@"SHOW /*!50002 FULL*/ TABLES"]; @@ -104,7 +111,8 @@ } else { for ( i = 0 ; i < [theResult numOfRows] ; i++ ) { resultRow = [theResult fetchRowAsArray]; - [tables addObject:[resultRow objectAtIndex:0]]; + NSString *tableName = [NSString stringWithUTF8String:[[resultRow objectAtIndex:0] cStringUsingEncoding:[mySQLConnection stringEncoding]]]; + [tables addObject:tableName]; if ([[resultRow objectAtIndex:1] isEqualToString:@"VIEW"]) { [tableTypes addObject:[NSNumber numberWithInteger:SPTableTypeView]]; tableListContainsViews = YES; @@ -206,7 +214,11 @@ } } } - */ + */ + + // Restore encoding if appropriate + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; + // Notify listeners that the query has finished [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance]; } @@ -695,6 +707,12 @@ { NSAutoreleasePool *selectionChangePool = [[NSAutoreleasePool alloc] init]; NSString *tableEncoding = nil; + NSString *previousEncoding = [mySQLConnection encoding]; + BOOL changeEncoding = ![previousEncoding isEqualToString:@"utf8"]; + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } // Update selection variables and interface NSDictionary *selectionDetails = [NSDictionary dictionaryWithObjectsAndKeys: @@ -702,8 +720,11 @@ [filteredTableTypes objectAtIndex:[tablesListView selectedRow]], @"type", nil]; [self performSelectorOnMainThread:@selector(setSelection:) withObject:selectionDetails waitUntilDone:YES]; - - // Check the encoding if appropriate to determine if an encoding change and reset is required + + // Ensure status information is cached on the working thread + [tableDataInstance updateStatusInformationForCurrentTable]; + + // Check the encoding if appropriate to determine if an encoding change is required if( selectedTableType == SPTableTypeView || selectedTableType == SPTableTypeTable) { // tableEncoding == nil indicates that there was an error while retrieving table data @@ -712,16 +733,14 @@ // If encoding is set to Autodetect, update the connection character set encoding // based on the newly selected table's encoding - but only if it differs from the current encoding. if ([[[NSUserDefaults standardUserDefaults] objectForKey:SPDefaultEncoding] intValue] == SPEncodingAutodetect) { - if (tableEncoding != nil && ![tableEncoding isEqualToString:[tableDocumentInstance connectionEncoding]]) { + if (tableEncoding != nil && ![tableEncoding isEqualToString:previousEncoding]) { [tableDocumentInstance setConnectionEncoding:tableEncoding reloadingViews:NO]; - [tableDataInstance resetAllData]; - tableEncoding = [tableDataInstance tableEncoding]; + changeEncoding = NO; } } } - // Ensure status information is cached on the working thread - [tableDataInstance updateStatusInformationForCurrentTable]; + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; // Notify listeners of the table change now that the state is fully set up. [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:SPTableChangedNotification object:tableDocumentInstance]; @@ -2154,6 +2173,13 @@ NSString *tableType = [tableTypeButton title]; NSString *tableName = [tableNameField stringValue]; + + // Ensure the use of UTF8 when creating new tables + BOOL changeEncoding = ![[mySQLConnection encoding] isEqualToString:@"utf8"]; + if (changeEncoding) { + [mySQLConnection storeEncodingForRestoration]; + [mySQLConnection setEncoding:@"utf8"]; + } // If there is an encoding selected other than the default we must specify it in CREATE TABLE statement if ([tableEncodingButton indexOfSelectedItem] > 0) { @@ -2226,7 +2252,8 @@ NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, @selector(sheetDidEnd:returnCode:contextInfo:), @"addRow", [NSString stringWithFormat:NSLocalizedString(@"An error occurred while trying to add the new table '%@'.\n\nMySQL said: %@", @"error adding new table informative message"), tableName, [mySQLConnection getLastErrorMessage]]); - + + if (changeEncoding) [mySQLConnection restoreStoredEncoding]; [tablesListView reloadData]; } diff --git a/Source/SPXMLExporterDelegate.m b/Source/SPXMLExporterDelegate.m index 17748bdc..e5073aed 100644 --- a/Source/SPXMLExporterDelegate.m +++ b/Source/SPXMLExporterDelegate.m @@ -71,7 +71,7 @@ // If we're exporting to multiple files then close the file handle of the exporter // that just finished, ensuring its data is written to disk. if (exportToMultipleFiles) { - [[exporter exportOutputFile] writeData:[[NSString stringWithFormat:@"</%@>\n", [[tableDocumentInstance database] HTMLEscapeString]] dataUsingEncoding:[connection encoding]]]; + [[exporter exportOutputFile] writeData:[[NSString stringWithFormat:@"</%@>\n", [[tableDocumentInstance database] HTMLEscapeString]] dataUsingEncoding:[connection stringEncoding]]]; [[exporter exportOutputFile] close]; } @@ -85,7 +85,7 @@ // Otherwise if the exporter list is empty, close the progress sheet else { if (exportSource == SPTableExport) { - [[exporter exportOutputFile] writeData:[[NSString stringWithFormat:@"</%@>\n", [[tableDocumentInstance database] HTMLEscapeString]] dataUsingEncoding:[connection encoding]]]; + [[exporter exportOutputFile] writeData:[[NSString stringWithFormat:@"</%@>\n", [[tableDocumentInstance database] HTMLEscapeString]] dataUsingEncoding:[connection stringEncoding]]]; } // Close the last exporter's file handle |