aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPTableStructureLoading.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPTableStructureLoading.m')
-rw-r--r--Source/SPTableStructureLoading.m194
1 files changed, 91 insertions, 103 deletions
diff --git a/Source/SPTableStructureLoading.m b/Source/SPTableStructureLoading.m
index 5a1e8e10..b7f8e748 100644
--- a/Source/SPTableStructureLoading.m
+++ b/Source/SPTableStructureLoading.m
@@ -36,6 +36,8 @@
#import "SPIndexesController.h"
#import "SPTablesList.h"
#import "SPThreadAdditions.h"
+#import "SPTableView.h"
+#import "SPFunctions.h"
#import <SPMySQL/SPMySQL.h>
@@ -77,10 +79,11 @@
[[self onMainThread] setTableDetails:nil];
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
- 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 lastErrorMessage]]);
+ SPOnewayAlertSheet(
+ NSLocalizedString(@"Error", @"error"),
+ [NSApp mainWindow],
+ [NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving information.\nMySQL said: %@", @"message of panel when retrieving information failed"), [mySQLConnection lastErrorMessage]]
+ );
}
return;
@@ -114,115 +117,97 @@
// Set up the encoding PopUpButtonCell
NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings];
-
- if ([encodings count]) {
- NSString *defaultEncodingDescription = nil;
-
- // Populate encoding popup button
- NSMutableArray *encodingTitles = [[NSMutableArray alloc] initWithCapacity:[encodings count]+1];
-
- [encodingTitles addObject:@""];
-
- for (NSDictionary *encoding in encodings)
- {
- [encodingTitles addObject:(![encoding objectForKey:@"DESCRIPTION"]) ? [encoding objectForKey:@"CHARACTER_SET_NAME"] : [NSString stringWithFormat:@"%@ (%@)", [encoding objectForKey:@"DESCRIPTION"], [encoding objectForKey:@"CHARACTER_SET_NAME"]]];
- if ([[encoding objectForKey:@"CHARACTER_SET_NAME"] isEqualToString:[tableDataInstance tableEncoding]]) {
- defaultEncodingDescription = [encodingTitles lastObject];
- }
- }
-
- [[encodingPopupCell onMainThread] removeAllItems];
- [[encodingPopupCell onMainThread] addItemsWithTitles:encodingTitles];
- // Take the encoding that matches the table's encoding and gray it out
- if (defaultEncodingDescription) {
- NSMenuItem *tableEncodingMenuItem = [[encodingPopupCell menu] itemWithTitle:defaultEncodingDescription];
- NSMutableParagraphStyle *menuStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
-
- [menuStyle setLineBreakMode:NSLineBreakByTruncatingTail];
-
- NSMutableDictionary *menuAttributes = [NSMutableDictionary dictionaryWithObject:[NSColor lightGrayColor] forKey:NSForegroundColorAttributeName];
+ SPMainQSync(^{
+ [encodingPopupCell removeAllItems];
- CGFloat monospacedFontSize = [prefs floatForKey:SPMonospacedFontSize] > 0 ? [prefs floatForKey:SPMonospacedFontSize] : [NSFont smallSystemFontSize];
+ if ([encodings count]) {
- [menuAttributes setObject:[prefs boolForKey:SPUseMonospacedFonts] ? [NSFont fontWithName:SPDefaultMonospacedFontName size:monospacedFontSize] : [NSFont systemFontOfSize:[NSFont smallSystemFontSize]] forKey:NSFontAttributeName];
-
- NSAttributedString *itemString = [[[NSAttributedString alloc] initWithString:defaultEncodingDescription attributes:menuAttributes] autorelease];
-
- [[tableEncodingMenuItem onMainThread] setAttributedTitle:itemString];
- }
+ [encodingPopupCell addItemWithTitle:@"dummy"];
+ //copy the default attributes and add gray color
+ NSMutableDictionary *defaultAttrs = [NSMutableDictionary dictionaryWithDictionary:[[encodingPopupCell attributedTitle] attributesAtIndex:0 effectiveRange:NULL]];
+ [defaultAttrs setObject:[NSColor lightGrayColor] forKey:NSForegroundColorAttributeName];
+ [[encodingPopupCell lastItem] setTitle:@""];
- [encodingTitles release];
- }
- else {
- [[encodingPopupCell onMainThread] removeAllItems];
- [[encodingPopupCell onMainThread] addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
- }
+ for (NSDictionary *encoding in encodings)
+ {
+ NSString *encodingName = [encoding objectForKey:@"CHARACTER_SET_NAME"];
+ NSString *title = (![encoding objectForKey:@"DESCRIPTION"]) ? encodingName : [NSString stringWithFormat:@"%@ (%@)", [encoding objectForKey:@"DESCRIPTION"], encodingName];
+
+ [encodingPopupCell addItemWithTitle:title];
+ NSMenuItem *item = [encodingPopupCell lastItem];
+
+ [item setRepresentedObject:encodingName];
+
+ if ([encodingName isEqualToString:[tableDataInstance tableEncoding]]) {
+
+ NSAttributedString *itemString = [[NSAttributedString alloc] initWithString:[item title] attributes:defaultAttrs];
+
+ [item setAttributedTitle:[itemString autorelease]];
+ }
+ }
+ }
+ else {
+ [encodingPopupCell addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
+ }
+ });
// Process all the fields to normalise keys and add additional information
for (id theField in theTableFields)
{
- // Select and re-map encoding and collation since [self dataSource] stores the choice as NSNumbers
- NSString *fieldEncoding = @"";
- NSInteger selectedIndex = 0;
-
NSString *type = [[[theField objectForKey:@"type"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString];
-
- NSString *collation = nil;
- NSString *encoding = nil;
-
- if ([fieldValidation isFieldTypeString:type]) {
-
- collation = [theField objectForKey:@"collation"] ? [theField objectForKey:@"collation"] : [[tableDataInstance statusValues] objectForKey:@"collation"];
- encoding = [theField objectForKey:@"encoding"] ? [theField objectForKey:@"encoding"] : [tableDataInstance tableEncoding];
-
- // If we still don't have a collation then fallback on the database default (not available on MySQL < 4.1.1).
- if (!collation) {
- collation = [databaseDataInstance getDatabaseDefaultCollation];
- }
- }
- if (encoding) {
- for (id enc in encodings)
- {
- if ([[enc objectForKey:@"CHARACTER_SET_NAME"] isEqualToString:encoding]) {
- fieldEncoding = encoding;
-
- // Set the selected index as the match index +1 due to the leading @"" in the popup list
- [theField setObject:[NSNumber numberWithInteger:(selectedIndex + 1)] forKey:@"encoding"];
- break;
+ if([type isEqualToString:@"JSON"]) {
+ // MySQL 5.7 manual:
+ // "MySQL handles strings used in JSON context using the utf8mb4 character set and utf8mb4_bin collation.
+ // Strings in other character set are converted to utf8mb4 as necessary."
+ [theField setObject:@"utf8mb4" forKey:@"encodingName"];
+ [theField setObject:@"utf8mb4_bin" forKey:@"collationName"];
+ [theField setObject:@1 forKey:@"binary"];
+ }
+ else if ([fieldValidation isFieldTypeString:type]) {
+ // The MySQL 4.1 manual says:
+ //
+ // MySQL chooses the column character set and collation in the following manner:
+ // 1. If both CHARACTER SET X and COLLATE Y were specified, then character set X and collation Y are used.
+ // 2. If CHARACTER SET X was specified without COLLATE, then character set X and its default collation are used.
+ // 3. If COLLATE Y was specified without CHARACTER SET, then the character set associated with Y and collation Y.
+ // 4. Otherwise, the table character set and collation are used.
+ NSString *encoding = [theField objectForKey:@"encoding"];
+ NSString *collation = [theField objectForKey:@"collation"];
+ if(encoding) {
+ if(collation) {
+ // 1
+ }
+ else {
+ collation = [databaseDataInstance getDefaultCollationForEncoding:encoding]; // 2
}
-
- selectedIndex++;
}
- }
-
- selectedIndex = 0;
-
- if (encoding && collation) {
-
- NSArray *theCollations = [databaseDataInstance getDatabaseCollationsForEncoding:fieldEncoding];
-
- for (id col in theCollations)
- {
- if ([[col objectForKey:@"COLLATION_NAME"] isEqualToString:collation]) {
-
- // Set the selected index as the match index +1 due to the leading @"" in the popup list
- [theField setObject:[NSNumber numberWithInteger:(selectedIndex + 1)] forKey:@"collation"];
-
- // Set BINARY if collation ends with _bin for convenience
- if ([[col objectForKey:@"COLLATION_NAME"] hasSuffix:@"_bin"]) {
- [theField setObject:@1 forKey:@"binary"];
+ else {
+ if(collation) {
+ encoding = [databaseDataInstance getEncodingFromCollation:collation]; // 3
+ }
+ else {
+ encoding = [tableDataInstance tableEncoding]; //4
+ collation = [tableDataInstance statusValueForKey:@"Collation"];
+ if(!collation) {
+ // should not happen, as the TABLE STATUS output always(?) includes the collation
+ collation = [databaseDataInstance getDefaultCollationForEncoding:encoding];
}
-
- break;
}
-
- selectedIndex++;
+ }
+
+ // MySQL < 4.1 does not support collations (they are part of the charset), it will be nil there
+
+ [theField setObject:encoding forKey:@"encodingName"];
+ [theField setObject:collation forKey:@"collationName"];
+
+ // Set BINARY if collation ends with _bin for convenience
+ if ([collation hasSuffix:@"_bin"]) {
+ [theField setObject:@1 forKey:@"binary"];
}
}
-
// Get possible values if the field is an enum or a set
if (([type isEqualToString:@"ENUM"] || [type isEqualToString:@"SET"]) && [theField objectForKey:@"values"]) {
[theTableEnumLists setObject:[NSArray arrayWithArray:[theField objectForKey:@"values"]] forKey:[theField objectForKey:@"name"]];
@@ -250,9 +235,15 @@
}
// For timestamps/datetime check to see whether "on update CURRENT_TIMESTAMP" and set Extra accordingly
- else if (([type isEqualToString:@"TIMESTAMP"] || [type isEqualToString:@"DATETIME"]) &&
- [[theField objectForKey:@"onupdatetimestamp"] integerValue]) {
- [theField setObject:@"on update CURRENT_TIMESTAMP" forKey:@"Extra"];
+ else if ([type isInArray:@[@"TIMESTAMP",@"DATETIME"]] && [[theField objectForKey:@"onupdatetimestamp"] boolValue]) {
+ NSString *ouct = @"on update CURRENT_TIMESTAMP";
+ // restore a length parameter if the field has fractional seconds.
+ // the parameter of current_timestamp MUST match the field's length in that case, so we can just 'guess' it.
+ NSString *fieldLen = [theField objectForKey:@"length"];
+ if([fieldLen length] && ![fieldLen isEqualToString:@"0"]) {
+ ouct = [ouct stringByAppendingFormat:@"(%@)",fieldLen];
+ }
+ [theField setObject:ouct forKey:@"Extra"];
}
}
@@ -287,10 +278,7 @@
[tableDocumentInstance setStatusRequiresReload:YES];
// Query the structure of all databases in the background (mainly for completion)
- [NSThread detachNewThreadWithName:SPCtxt(@"SPNavigatorController database structure querier", tableDocumentInstance)
- target:[tableDocumentInstance databaseStructureRetrieval]
- selector:@selector(queryDbStructureWithUserInfo:)
- object:@{@"forceUpdate" : @YES}];
+ [[tableDocumentInstance databaseStructureRetrieval] queryDbStructureInBackgroundWithUserInfo:@{@"forceUpdate" : @YES}];
[self loadTable:selectedTable];
}