aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/SPExtendedTableInfo.m180
-rw-r--r--Source/SPTableData.m114
-rw-r--r--Source/SPTableInfo.m73
3 files changed, 212 insertions, 155 deletions
diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m
index f9e0bdb8..186c4c25 100644
--- a/Source/SPExtendedTableInfo.m
+++ b/Source/SPExtendedTableInfo.m
@@ -50,11 +50,11 @@
- (void)awakeFromNib
{
[tableCreateSyntaxTextView setAllowsDocumentBackgroundColorChange:YES];
-
+
NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary];
-
+
[bindingOptions setObject:NSUnarchiveFromDataTransformerName forKey:@"NSValueTransformerName"];
-
+
[tableCreateSyntaxTextView bind:@"backgroundColor"
toObject:[NSUserDefaultsController sharedUserDefaultsController]
withKeyPath:@"values.CustomQueryEditorBackgroundColor"
@@ -81,7 +81,7 @@
{
// Reset the table data's cache
[tableDataInstance resetAllData];
-
+
// Load the new table info
[self loadTable:selectedTable];
}
@@ -98,18 +98,18 @@
if ([currentType isEqualToString:newType]) {
return;
}
-
+
// Alter table's storage type
[connection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ TYPE = %@", [selectedTable backtickQuotedString], newType]];
-
+
if ([connection getLastErrorID] == 0) {
// Reload the table's data
[tablesListInstance updateSelectionWithTaskString:NSLocalizedString(@"Reloading data...", @"Reloading data task description")];
}
else {
[sender selectItemWithTitle:currentType];
-
- SPBeginAlertSheet(NSLocalizedString(@"Error changing table type", @"error changing table type message"),
+
+ SPBeginAlertSheet(NSLocalizedString(@"Error changing table type", @"error changing table type message"),
NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the table type to '%@'.\n\nMySQL said: %@", @"error changing table type informative message"), newType, [connection getLastErrorMessage]]);
}
@@ -122,21 +122,21 @@
{
NSString *currentEncoding = [tableDataInstance tableEncoding];
NSString *newEncoding = [[sender titleOfSelectedItem] stringByMatching:@"^.+\\((.+)\\)$" capture:1L];
-
+
// Check if the user selected the same encoding
if ([currentEncoding isEqualToString:newEncoding]) return;
-
+
// Alter table's character set encoding
[connection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ CHARACTER SET = %@", [selectedTable backtickQuotedString], newEncoding]];
-
+
if ([connection getLastErrorID] == 0) {
// Reload the table's data
[self reloadTable:self];
}
else {
[sender selectItemWithTitle:currentEncoding];
-
- SPBeginAlertSheet(NSLocalizedString(@"Error changing table encoding", @"error changing table encoding message"),
+
+ SPBeginAlertSheet(NSLocalizedString(@"Error changing table encoding", @"error changing table encoding message"),
NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the table encoding to '%@'.\n\nMySQL said: %@", @"error changing table encoding informative message"), newEncoding, [connection getLastErrorMessage]]);
}
@@ -149,21 +149,21 @@
{
NSString *newCollation = [sender titleOfSelectedItem];
NSString *currentCollation = [tableDataInstance statusValueForKey:@"Collation"];
-
+
// Check if the user selected the same collation
if ([currentCollation isEqualToString:newCollation]) return;
-
+
// Alter table's character set collation
[connection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ COLLATE = %@", [selectedTable backtickQuotedString], newCollation]];
-
+
if ([connection getLastErrorID] == 0) {
// Reload the table's data
[self reloadTable:self];
}
else {
[sender selectItemWithTitle:currentCollation];
-
- SPBeginAlertSheet(NSLocalizedString(@"Error changing table collation", @"error changing table collation message"),
+
+ SPBeginAlertSheet(NSLocalizedString(@"Error changing table collation", @"error changing table collation message"),
NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the table collation to '%@'.\n\nMySQL said: %@", @"error changing table collation informative message"), newCollation, [connection getLastErrorMessage]]);
}
@@ -174,7 +174,7 @@
if ([sender tag] == 1) {
[tableRowAutoIncrement setEditable:YES];
[tableRowAutoIncrement selectText:nil];
- }
+ }
else {
[tableRowAutoIncrement setEditable:NO];
[tableSourceInstance resetAutoIncrement:sender];
@@ -187,58 +187,58 @@
[tableSourceInstance setAutoIncrementTo:[[tableRowAutoIncrement stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
}
-- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command
+- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command
{
// Listen to ESC to abort editing of auto increment input field
if (command == @selector(cancelOperation:) && control == tableRowAutoIncrement) {
[tableRowAutoIncrement abortEditing];
return YES;
}
-
+
return NO;
}
#pragma mark -
#pragma mark Other
-
+
/**
- * Load all the info for the supplied table by querying the table data instance and updaing the interface
+ * Load all the info for the supplied table by querying the table data instance and updaing the interface
* elements accordingly.
* Note that interface elements are also toggled in start/endDocumentTaskForTab:, with similar logic.
* Due to the large quantity of interface interaction in this function it is not thread-safe.
*/
- (void)loadTable:(NSString *)table
-{
+{
BOOL enableInteraction = ![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableInfo] || ![tableDocumentInstance isWorking];
[resetAutoIncrementResetButton setHidden:YES];
// Store the table name away for future use
selectedTable = table;
-
+
// Retrieve the table status information via the table data cache
NSDictionary *statusFields = [tableDataInstance statusValues];
-
+
[tableTypePopUpButton removeAllItems];
[tableEncodingPopUpButton removeAllItems];
[tableCollationPopUpButton removeAllItems];
-
+
// No table selected or view selected
if ((!table) || [table isEqualToString:@""] || [[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) {
-
+
[tableTypePopUpButton setEnabled:NO];
[tableEncodingPopUpButton setEnabled:NO];
[tableCollationPopUpButton setEnabled:NO];
-
+
if ([[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) {
[tableTypePopUpButton addItemWithTitle:@"View"];
// Set create syntax
[tableCreateSyntaxTextView setEditable:YES];
[tableCreateSyntaxTextView shouldChangeTextInRange:NSMakeRange(0, [[tableCreateSyntaxTextView string] length]) replacementString:@""];
[tableCreateSyntaxTextView setString:@""];
-
+
NSString *createViewSyntax = [[[tableDataInstance tableCreateSyntax] createViewSyntaxPrettifier] stringByAppendingString:@";"];
-
+
if (createViewSyntax) {
[tableCreateSyntaxTextView shouldChangeTextInRange:NSMakeRange(0, 0) replacementString:createViewSyntax];
[tableCreateSyntaxTextView insertText:createViewSyntax];
@@ -252,101 +252,105 @@
[tableCreateSyntaxTextView didChangeText];
[tableCreateSyntaxTextView setEditable:NO];
}
-
+
[tableCreatedAt setStringValue:@""];
[tableUpdatedAt setStringValue:@""];
-
+
// Set row values
[tableRowNumber setStringValue:@""];
[tableRowFormat setStringValue:@""];
[tableRowAvgLength setStringValue:@""];
[tableRowAutoIncrement setStringValue:@""];
-
+
// Set size values
[tableDataSize setStringValue:@""];
[tableMaxDataSize setStringValue:@""];
[tableIndexSize setStringValue:@""];
[tableSizeFree setStringValue:@""];
-
- // Set comments
+
+ // Set comments
[tableCommentsTextView setEditable:NO];
[tableCommentsTextView shouldChangeTextInRange:NSMakeRange(0, [[tableCommentsTextView string] length]) replacementString:@""];
[tableCommentsTextView setString:@""];
[tableCommentsTextView didChangeText];
-
+
+ if([[statusFields objectForKey:@"Engine"] isEqualToString:@"View"] && [statusFields objectForKey:@"CharacterSetClient"] && [statusFields objectForKey:@"Collation"]) {
+ [tableEncodingPopUpButton addItemWithTitle:[statusFields objectForKey:@"CharacterSetClient"]];
+ [tableCollationPopUpButton addItemWithTitle:[statusFields objectForKey:@"Collation"]];
+ }
return;
}
-
+
NSArray *engines = [databaseDataInstance getDatabaseStorageEngines];
NSArray *encodings = [databaseDataInstance getDatabaseCharacterSetEncodings];
NSArray *collations = [databaseDataInstance getDatabaseCollationsForEncoding:[tableDataInstance tableEncoding]];
-
+
if (([engines count] > 0) && ([statusFields objectForKey:@"Engine"])) {
-
+
// Populate type popup button
for (NSDictionary *engine in engines)
- {
+ {
[tableTypePopUpButton addItemWithTitle:[engine objectForKey:@"Engine"]];
- }
-
+ }
+
[tableTypePopUpButton selectItemWithTitle:[statusFields objectForKey:@"Engine"]];
[tableTypePopUpButton setEnabled:enableInteraction];
}
else {
[tableTypePopUpButton addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
}
-
+
if (([encodings count] > 0) && ([tableDataInstance tableEncoding])) {
NSString *selectedTitle = @"";
-
+
// Populate encoding popup button
for (NSDictionary *encoding in encodings)
- {
+ {
NSString *menuItemTitle = (![encoding objectForKey:@"DESCRIPTION"]) ? [encoding objectForKey:@"CHARACTER_SET_NAME"] : [NSString stringWithFormat:@"%@ (%@)", [encoding objectForKey:@"DESCRIPTION"], [encoding objectForKey:@"CHARACTER_SET_NAME"]];
-
+
[tableEncodingPopUpButton addItemWithTitle:menuItemTitle];
-
+
if ([[tableDataInstance tableEncoding] isEqualToString:[encoding objectForKey:@"CHARACTER_SET_NAME"]]) {
selectedTitle = menuItemTitle;
}
- }
-
+ }
+
[tableEncodingPopUpButton selectItemWithTitle:selectedTitle];
[tableEncodingPopUpButton setEnabled:enableInteraction];
}
else {
[tableEncodingPopUpButton addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
}
-
+
if (([collations count] > 0) && ([statusFields objectForKey:@"Collation"])) {
// Populate collation popup button
for (NSDictionary *collation in collations)
- {
+ {
[tableCollationPopUpButton addItemWithTitle:[collation objectForKey:@"COLLATION_NAME"]];
- }
-
+ }
+
[tableCollationPopUpButton selectItemWithTitle:[statusFields objectForKey:@"Collation"]];
[tableCollationPopUpButton setEnabled:enableInteraction];
}
else {
[tableCollationPopUpButton addItemWithTitle:NSLocalizedString(@"Not available", @"not available label")];
}
-
+
[tableCreatedAt setStringValue:[self _formatValueWithKey:@"Create_time" inDictionary:statusFields]];
[tableUpdatedAt setStringValue:[self _formatValueWithKey:@"Update_time" inDictionary:statusFields]];
-
+
// Set row values
[tableRowNumber setStringValue:[self _formatValueWithKey:@"Rows" inDictionary:statusFields]];
[tableRowFormat setStringValue:[self _formatValueWithKey:@"Row_format" inDictionary:statusFields]];
[tableRowAvgLength setStringValue:[self _formatValueWithKey:@"Avg_row_length" inDictionary:statusFields]];
[tableRowAutoIncrement setStringValue:[self _formatValueWithKey:@"Auto_increment" inDictionary:statusFields]];
-
+
// Set size values
[tableDataSize setStringValue:[self _formatValueWithKey:@"Data_length" inDictionary:statusFields]];
[tableMaxDataSize setStringValue:[self _formatValueWithKey:@"Max_data_length" inDictionary:statusFields]];
[tableIndexSize setStringValue:[self _formatValueWithKey:@"Index_length" inDictionary:statusFields]];
[tableSizeFree setStringValue:[self _formatValueWithKey:@"Data_free" inDictionary:statusFields]];
-
+
// Set comments
NSString *commentText = [statusFields objectForKey:@"Comment"];
if (!commentText) commentText = @"";
@@ -355,7 +359,7 @@
[tableCommentsTextView setString:commentText];
[tableCommentsTextView didChangeText];
[tableCommentsTextView setEditable:enableInteraction];
-
+
// Set create syntax
[tableCreateSyntaxTextView setEditable:YES];
[tableCreateSyntaxTextView shouldChangeTextInRange:NSMakeRange(0, [[tableCommentsTextView string] length]) replacementString:@""];
@@ -367,7 +371,7 @@
}
[tableCreateSyntaxTextView didChangeText];
[tableCreateSyntaxTextView setEditable:NO];
-
+
// Validate Reset AUTO_INCREMENT button
if ([statusFields objectForKey:@"Auto_increment"] && ![[statusFields objectForKey:@"Auto_increment"] isKindOfClass:[NSNull class]]) {
[resetAutoIncrementResetButton setHidden:NO];
@@ -418,8 +422,8 @@
NSError *error = nil;
NSArray *HTMLExcludes = [NSArray arrayWithObjects:@"doctype", @"html", @"head", @"body", @"xml", nil];
-
- NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType,
+
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:NSHTMLTextDocumentType,
NSDocumentTypeDocumentAttribute, HTMLExcludes, NSExcludedElementsDocumentAttribute, nil];
// Set tableCreateSyntaxTextView's font size temporarily to 10pt for printing
@@ -429,13 +433,13 @@
[tableCreateSyntaxTextView setFont:[NSFont fontWithName:[oldFont fontName] size:10.0]];
// Convert tableCreateSyntaxTextView to HTML
- NSData *HTMLData = [[tableCreateSyntaxTextView textStorage] dataFromRange:NSMakeRange(0, [[tableCreateSyntaxTextView string] length])
+ NSData *HTMLData = [[tableCreateSyntaxTextView textStorage] dataFromRange:NSMakeRange(0, [[tableCreateSyntaxTextView string] length])
documentAttributes:attributes error:&error];
// Restore original font settings
[tableCreateSyntaxTextView setFont:oldFont];
[tableCreateSyntaxTextView setEditable:editableStatus];
-
+
if (error != nil) {
NSLog(@"Error generating table's create syntax HTML for printing. Excluding from print out. Error was: %@", [error localizedDescription]);
@@ -445,7 +449,7 @@
NSString *HTMLString = [[[NSString alloc] initWithData:HTMLData encoding:NSUTF8StringEncoding] autorelease];
[tableInfo setObject:HTMLString forKey:@"createSyntax"];
-
+
return tableInfo;
}
@@ -455,24 +459,24 @@
- (void)textDidEndEditing:(NSNotification *)notification
{
id object = [notification object];
-
+
if ((object == tableCommentsTextView) && ([object isEditable]) && ([selectedTable length] > 0)) {
-
+
NSString *currentComment = [[tableDataInstance statusValueForKey:@"Comment"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *newComment = [[tableCommentsTextView string] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
// Check that the user actually changed the tables comment
if (![currentComment isEqualToString:newComment]) {
-
+
// Alter table's comment
[connection queryString:[NSString stringWithFormat:@"ALTER TABLE %@ COMMENT = '%@'", [selectedTable backtickQuotedString], [connection prepareString:newComment]]];
-
+
if ([connection getLastErrorID] == 0) {
// Reload the table's data
[self reloadTable:self];
}
else {
- SPBeginAlertSheet(NSLocalizedString(@"Error changing table comment", @"error changing table comment message"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error changing table comment", @"error changing table comment message"),
NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred when trying to change the table's comment to '%@'.\n\nMySQL said: %@", @"error changing table comment informative message"), newComment, [connection getLastErrorMessage]]);
}
@@ -506,13 +510,13 @@
if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:SPMainToolbarTableInfo]) return;
NSDictionary *statusFields = [tableDataInstance statusValues];
-
+
if (!selectedTable || ![selectedTable length] || [[statusFields objectForKey:@"Engine"] isEqualToString:@"View"]) return;
// If we are viewing tables in the information_schema database, then disable all controls that cause table
// changes as these tables are not modifiable by anyone.
BOOL isInformationSchemaDb = [[tableDocumentInstance database] isEqualToString:@"information_schema"];
-
+
if ([[databaseDataInstance getDatabaseStorageEngines] count] && [statusFields objectForKey:@"Engine"]) {
[tableTypePopUpButton setEnabled:(!isInformationSchemaDb)];
}
@@ -540,7 +544,7 @@
[[NSNotificationCenter defaultCenter] removeObserver:self];
[connection release], connection = nil;
-
+
[super dealloc];
}
@@ -549,45 +553,45 @@
@implementation SPExtendedTableInfo (PrivateAPI)
/**
- * Format and returns the value within the info dictionary with the associated key.
+ * Format and returns the value within the info dictionary with the associated key.
*/
- (NSString *)_formatValueWithKey:(NSString *)key inDictionary:(NSDictionary *)infoDict
{
NSString *value = [infoDict objectForKey:key];
-
+
if ([value isKindOfClass:[NSNull class]]) {
value = @"";
- }
+ }
else {
// Format size strings
- if ([key isEqualToString:@"Data_length"] ||
- [key isEqualToString:@"Max_data_length"] ||
- [key isEqualToString:@"Index_length"] ||
+ if ([key isEqualToString:@"Data_length"] ||
+ [key isEqualToString:@"Max_data_length"] ||
+ [key isEqualToString:@"Index_length"] ||
[key isEqualToString:@"Data_free"]) {
-
+
value = [NSString stringForByteSize:[value longLongValue]];
}
// Format date strings to the user's long date format
else if ([key isEqualToString:@"Create_time"] ||
[key isEqualToString:@"Update_time"]) {
-
+
// Create date formatter
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
-
+
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
-
+
[dateFormatter setDateStyle:NSDateFormatterLongStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
-
+
value = [dateFormatter stringFromDate:[NSDate dateWithNaturalLanguageString:value]];
}
// Format numbers
else if ([key isEqualToString:@"Rows"] ||
- [key isEqualToString:@"Avg_row_length"] ||
+ [key isEqualToString:@"Avg_row_length"] ||
[key isEqualToString:@"Auto_increment"]) {
-
+
NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
-
+
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
value = [numberFormatter stringFromNumber:[NSNumber numberWithLongLong:[value longLongValue]]];
@@ -598,7 +602,7 @@
}
}
}
-
+
if ([key isEqualToString:@"Auto_increment"]) {
return ([value length] > 0) ? value : NSLocalizedString(@"Not available", @"not available label");
}
diff --git a/Source/SPTableData.m b/Source/SPTableData.m
index a6a5819a..db9cccfe 100644
--- a/Source/SPTableData.m
+++ b/Source/SPTableData.m
@@ -62,7 +62,7 @@
[mySQLConnection retain];
}
-
+
/*
* Retrieve the encoding for the current table, using or refreshing the cache as appropriate.
*/
@@ -86,7 +86,7 @@
if (tableCreateSyntax == nil) {
if ([tableListInstance tableType] == SPTableTypeView) {
[self updateInformationForCurrentView];
- }
+ }
else {
[self updateInformationForCurrentTable];
}
@@ -141,7 +141,7 @@
* Retrieve a column with a specified name, using or refreshing the cache as appropriate.
*/
- (NSDictionary *) columnWithName:(NSString *)colName
-{
+{
if ([columns count] == 0) {
if ([tableListInstance tableType] == SPTableTypeView) {
[self updateInformationForCurrentView];
@@ -159,7 +159,7 @@
* Retrieve column names for the current table as an array, using or refreshing the cache as appropriate.
*/
- (NSArray *) columnNames
-{
+{
if ([columnNames count] == 0) {
if ([tableListInstance tableType] == SPTableTypeView) {
[self updateInformationForCurrentView];
@@ -175,7 +175,7 @@
* Retrieve a specified column for the current table as a dictionary, using or refreshing the cache as appropriate.
*/
- (NSDictionary *) columnAtIndex:(NSInteger)index
-{
+{
if ([columns count] == 0) {
if ([tableListInstance tableType] == SPTableTypeView) {
[self updateInformationForCurrentView];
@@ -186,13 +186,13 @@
return [columns objectAtIndex:index];
}
-/*
+/*
* Checks if this column is type text or blob.
* Used to determine if we have to show a popup when we edit a value from this column.
*/
- (BOOL) columnIsBlobOrText:(NSString *)colName
-{
+{
if ([columns count] == 0) {
if ([tableListInstance tableType] == SPTableTypeView) {
[self updateInformationForCurrentView];
@@ -200,7 +200,7 @@
[self updateInformationForCurrentTable];
}
}
-
+
return (BOOL) ([[[self columnWithName:colName] objectForKey:@"typegrouping"] isEqualToString:@"textdata" ] || [[[self columnWithName:colName] objectForKey:@"typegrouping"] isEqualToString:@"blobdata"]);
}
@@ -221,7 +221,7 @@
* via other means and are subsequently more accurate than the value currently set.
*/
- (void)setStatusValue:(NSString *)value forKey:(NSString *)key
-{
+{
[status setValue:value forKey:key];
}
@@ -246,17 +246,17 @@
[columns removeAllObjects];
[columnNames removeAllObjects];
[status removeAllObjects];
-
+
if (triggers != nil) {
[triggers release];
triggers = nil;
}
-
+
if (tableEncoding != nil) {
[tableEncoding release];
tableEncoding = nil;
}
-
+
if (tableCreateSyntax != nil) {
[tableCreateSyntax release];
tableCreateSyntax = nil;
@@ -292,15 +292,15 @@
NSDictionary *tableData = nil;
NSDictionary *columnData;
NSEnumerator *enumerator;
-
+
[columns removeAllObjects];
[columnNames removeAllObjects];
[constraints removeAllObjects];
- if( [tableListInstance tableType] == SPTableTypeTable || [tableListInstance tableType] == SPTableTypeView ) {
+ if( [tableListInstance tableType] == SPTableTypeTable || [tableListInstance tableType] == SPTableTypeView ) {
tableData = [self informationForTable:[tableListInstance tableName]];
}
-
+
if (tableData == nil ) {
return FALSE;
}
@@ -311,7 +311,7 @@
while (columnData = [enumerator nextObject]) {
[columnNames addObject:[NSString stringWithString:[columnData objectForKey:@"name"]]];
}
-
+
if (tableEncoding != nil) {
[tableEncoding release];
}
@@ -330,7 +330,7 @@
* Returns a boolean indicating success.
*/
- (NSDictionary *) informationForTable:(NSString *)tableName
-{
+{
SPSQLParser *createTableParser, *fieldsParser, *fieldParser;
NSMutableArray *tableColumns, *fieldStrings;
NSMutableDictionary *tableColumn, *tableData;
@@ -342,7 +342,7 @@
[columns removeAllObjects];
[columnNames removeAllObjects];
[constraints removeAllObjects];
-
+
// Catch unselected tables and return nil
if ([tableName isEqualToString:@""] || !tableName) return nil;
@@ -355,11 +355,11 @@
// Retrieve the CREATE TABLE syntax for the table
MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW CREATE TABLE %@", [tableName backtickQuotedString]]];
[theResult setReturnDataAsStrings:YES];
-
+
// Check for any errors, but only display them if a connection still exists
if ([mySQLConnection queryErrored]) {
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error retrieving table information", @"error retrieving table information message"), NSLocalizedString(@"OK", @"OK button"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error retrieving table information", @"error retrieving table information message"), NSLocalizedString(@"OK", @"OK button"),
nil, nil, [NSApp mainWindow], self, nil, nil,
[NSString stringWithFormat:NSLocalizedString(@"An error occurred while retrieving the information for table '%@'. Please try again.\n\nMySQL said: %@", @"error retrieving table information informative message"),
tableName, [mySQLConnection getLastErrorMessage]]);
@@ -370,18 +370,18 @@
}
if (changeEncoding) [mySQLConnection restoreStoredEncoding];
}
-
+
return nil;
}
// Retrieve the table syntax string
NSArray *syntaxResult = [theResult fetchRowAsArray];
NSArray *resultFieldNames = [theResult fetchFieldNames];
-
- // Only continue if syntaxResult is not nil. This accommodates causes where the above query caused the
+
+ // Only continue if syntaxResult is not nil. This accommodates causes where the above query caused the
// connection reconnect dialog to appear and the user chose to close the connection.
if (!syntaxResult) return nil;
-
+
if (tableCreateSyntax != nil) [tableCreateSyntax release], tableCreateSyntax = nil;
// A NULL value indicates that the user does not have permission to view the syntax
@@ -410,7 +410,7 @@
tableColumns = [[NSMutableArray alloc] init];
tableColumn = [[NSMutableDictionary alloc] init];
fieldParser = [[SPSQLParser alloc] init];
-
+
NSCharacterSet *whitespaceAndNewlineSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSCharacterSet *quoteSet = [NSCharacterSet characterSetWithCharactersInString:@"`'\""];
NSCharacterSet *bracketSet = [NSCharacterSet characterSetWithCharactersInString:@"()"];
@@ -461,18 +461,18 @@
];
}
[fieldsParser setIgnoreCommentStrings:NO];
-
+
[tableColumn setObject:[NSNumber numberWithInteger:[tableColumns count]] forKey:@"datacolumnindex"];
[tableColumn setObject:fieldName forKey:@"name"];
// Split the remaining field definition string by spaces and process
[tableColumn addEntriesFromDictionary:[self parseFieldDefinitionStringParts:[fieldsParser splitStringByCharacter:' ' skippingBrackets:YES]]];
-
+
//if column is not null, but doesn't have a default value, set empty string
if([[tableColumn objectForKey:@"null"] integerValue] == 0 && [[tableColumn objectForKey:@"autoincrement"] integerValue] == 0 && ![tableColumn objectForKey:@"default"]) {
[tableColumn setObject:@"" forKey:@"default"];
}
-
+
// Store the column.
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:1];
[d setDictionary:tableColumn];
@@ -492,13 +492,13 @@
NSMutableArray *keyColumns = [NSMutableArray array];
NSArray *keyColumnStrings = [[[parts objectAtIndex:4] stringByTrimmingCharactersInSet:bracketSet] componentsSeparatedByString:@","];
-
+
for (NSString *keyColumn in keyColumnStrings)
{
[fieldsParser setString:[[keyColumn stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] stringByTrimmingCharactersInSet:bracketSet]];
[keyColumns addObject:[fieldsParser unquotedString]];
}
-
+
[constraintDetails setObject:keyColumns forKey:@"columns"];
[fieldsParser setString:[[parts objectAtIndex:6] stringByTrimmingCharactersInSet:bracketSet]];
@@ -523,7 +523,7 @@
[constraintDetails setObject:NSArrayObjectAtIndex(parts, 10)
forKey:@"update"];
}
- }
+ }
else if( [NSArrayObjectAtIndex(parts, 9) hasPrefix:@"DELETE"] ) {
if( [NSArrayObjectAtIndex(parts, 10) hasPrefix:@"SET"] ) {
[constraintDetails setObject:@"SET NULL"
@@ -551,7 +551,7 @@
[constraintDetails setObject:NSArrayObjectAtIndex(parts, nextOffs+1)
forKey:@"update"];
}
- }
+ }
else if( [NSArrayObjectAtIndex(parts, nextOffs) hasPrefix:@"DELETE"] ) {
if( [NSArrayObjectAtIndex(parts, nextOffs+1) hasPrefix:@"SET"] ) {
[constraintDetails setObject:@"SET NULL"
@@ -597,7 +597,7 @@
break;
}
}
-
+
}
}
// who knows
@@ -635,7 +635,7 @@
[createTableParser release];
[fieldParser release];
-
+
// this will be 'Table' or 'View'
[tableData setObject:[resultFieldNames objectAtIndex:0] forKey:@"type"];
@@ -675,7 +675,7 @@
while (columnData = [enumerator nextObject]) {
[columnNames addObject:[NSString stringWithString:[columnData objectForKey:@"name"]]];
}
-
+
if (tableEncoding != nil) {
[tableEncoding release];
}
@@ -720,7 +720,7 @@
// Check for any errors, but only display them if a connection still exists
if ([mySQLConnection queryErrored]) {
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
+ 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 getLastErrorMessage]]);
@@ -754,7 +754,7 @@
// Check for any errors, but only display them if a connection still exists
if ([mySQLConnection queryErrored]) {
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
+ 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 getLastErrorMessage]]);
@@ -826,13 +826,6 @@
if ([[tableListInstance tableName] isEqualToString:@""] || ![tableListInstance tableName])
return FALSE;
- // When views are selected, populate the table with a default dictionary - all values, including comment, return no
- // meaningful information for views so we may as well skip the query.
- if ([tableListInstance tableType] == SPTableTypeView) {
- [status setDictionary:[NSDictionary dictionaryWithObjectsAndKeys:@"View", @"Engine", @"No status information is available for views.", @"Comment", [tableListInstance tableName], @"Name", nil]];
- return TRUE;
- }
-
// Ensure queries are run as UTF8
if (changeEncoding) {
[mySQLConnection storeEncodingForRestoration];
@@ -855,6 +848,11 @@
[escapedDatabaseName replaceOccurrencesOfString:@"'" withString:@"\\\'" options:0 range:NSMakeRange(0, [escapedDatabaseName length])];
tableStatusResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM information_schema.ROUTINES AS r WHERE r.SPECIFIC_NAME = '%@' AND r.ROUTINE_SCHEMA = '%@' AND r.ROUTINE_TYPE = 'FUNCTION'", escapedTableName, escapedDatabaseName]];
}
+ else if ([tableListInstance tableType] == SPTableTypeView) {
+ NSMutableString *escapedDatabaseName = [NSMutableString stringWithString:[tableDocumentInstance database]];
+ [escapedDatabaseName replaceOccurrencesOfString:@"'" withString:@"\\\'" options:0 range:NSMakeRange(0, [escapedDatabaseName length])];
+ tableStatusResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM information_schema.VIEWS AS r WHERE r.TABLE_NAME = '%@' AND r.TABLE_SCHEMA = '%@'", escapedTableName, escapedDatabaseName]];
+ }
else if ([tableListInstance tableType] == SPTableTypeTable) {
tableStatusResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW TABLE STATUS LIKE '%@'", escapedTableName ]];
[tableStatusResult setReturnDataAsStrings:YES];
@@ -863,7 +861,7 @@
// Check for any errors, only displaying them if the connection hasn't been terminated
if ([mySQLConnection queryErrored]) {
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"),
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]]);
@@ -904,6 +902,18 @@
[status setObject:[[tableStatusResult fetchRowAsArray] objectAtIndex:0] forKey:@"Rows"];
[status setObject:@"y" forKey:@"RowsCountAccurate"];
}
+
+ }
+
+ // When views are selected, populate the table by adding some default information.
+ else if ([tableListInstance tableType] == SPTableTypeView) {
+ [status addEntriesFromDictionary:[NSDictionary dictionaryWithObjectsAndKeys:
+ @"View", @"Engine",
+ @"No status information is available for views.", @"Comment",
+ [tableListInstance tableName], @"Name",
+ [status objectForKey:@"COLLATION_CONNECTION"], @"Collation",
+ [status objectForKey:@"CHARACTER_SET_CLIENT"], @"CharacterSetClient",
+ nil]];
}
if (changeEncoding) [mySQLConnection restoreStoredEncoding];
@@ -924,14 +934,14 @@
[mySQLConnection setEncoding:@"utf8"];
}
- MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */",
+ MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"/*!50003 SHOW TRIGGERS WHERE `Table` = %@ */",
[[tableListInstance tableName] tickQuotedString]]];
[theResult setReturnDataAsStrings:YES];
-
+
// Check for any errors, but only display them if a connection still exists
if ([mySQLConnection queryErrored]) {
if ([mySQLConnection isConnected]) {
- SPBeginAlertSheet(NSLocalizedString(@"Error retrieving trigger information", @"error retrieving trigger information message"), NSLocalizedString(@"OK", @"OK button"),
+ SPBeginAlertSheet(NSLocalizedString(@"Error retrieving trigger information", @"error retrieving trigger information message"), NSLocalizedString(@"OK", @"OK button"),
nil, nil, [NSApp mainWindow], self, nil, nil,
[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]]);
@@ -1127,14 +1137,14 @@
&& [[[definitionParts objectAtIndex:definitionPartsIndex+2] uppercaseString] isEqualToString:@"CURRENT_TIMESTAMP"]) {
[fieldDetails setValue:[NSNumber numberWithBool:YES] forKey:@"onupdatetimestamp"];
definitionPartsIndex += 2;
-
+
// Column comments
} else if ([detailString isEqualToString:@"COMMENT"] && (definitionPartsIndex + 1 < partsArrayLength)) {
detailParser = [[SPSQLParser alloc] initWithString:[definitionParts objectAtIndex:definitionPartsIndex+1]];
[fieldDetails setValue:[detailParser unquotedString] forKey:@"comment"];
[detailParser release];
definitionPartsIndex++;
-
+
// Preserve unhandled details to avoid losing information when rearranging columns etc
// TODO: Currently unhandled: [UNIQUE | PRIMARY] KEY | COLUMN_FORMAT bar | STORAGE q | REFERENCES...
} else {
@@ -1187,7 +1197,7 @@
return nil;
}
-
+
for( i = 0; i < [r numOfRows]; i++ ) {
resultRow = [r fetchRowAsArray];
// check if the row is indeed a key (for MySQL servers before 5.0.3)
@@ -1211,7 +1221,7 @@
[columnNames release];
[constraints release];
[status release];
-
+
if (triggers) [triggers release];
if (tableEncoding) [tableEncoding release];
if (tableCreateSyntax) [tableCreateSyntax release];
diff --git a/Source/SPTableInfo.m b/Source/SPTableInfo.m
index 00db406e..61a0bb2c 100644
--- a/Source/SPTableInfo.m
+++ b/Source/SPTableInfo.m
@@ -50,8 +50,8 @@
- (void)awakeFromNib
{
[[NSNotificationCenter defaultCenter] addObserver:self
- selector:@selector(tableChanged:)
- name:SPTableChangedNotification
+ selector:@selector(tableChanged:)
+ name:SPTableChangedNotification
object:tableDocumentInstance];
[info addObject:NSLocalizedString(@"TABLE INFORMATION", @"header for table info pane")];
@@ -81,20 +81,12 @@
[info removeAllObjects];
- // For views, no information can be displayed.
- if ([tableListInstance tableType] == SPTableTypeView) {
- [info addObject:NSLocalizedString(@"VIEW INFORMATION", @"header for view info pane")];
- [info addObject:NSLocalizedString(@"no information available", @"no information available")];
- [infoTable reloadData];
- return;
- }
-
if ([[tableListInstance tableName] isEqualToString:@""]) {
[info addObject:NSLocalizedString(@"INFORMATION", @"header for blank info pane")];
[info addObject:NSLocalizedString(@"multiple selection", @"multiple selection")];
[infoTable reloadData];
return;
- }
+ }
// Get TABLE information
if ([tableListInstance tableType] == SPTableTypeTable) {
@@ -130,7 +122,7 @@
if (![[tableStatus objectForKey:@"Rows"] isNSNull]) {
[info addObject:[NSString stringWithFormat:[[tableStatus objectForKey:@"RowsCountAccurate"] boolValue] ? NSLocalizedString(@"rows: %@", @"rows: %@") : NSLocalizedString(@"rows: ~%@", @"rows: ~%@"),
[numberFormatter stringFromNumber:[NSNumber numberWithLongLong:[[tableStatus objectForKey:@"Rows"] longLongValue]]]]];
- }
+ }
[info addObject:[NSString stringWithFormat:NSLocalizedString(@"size: %@", @"size: %@"), [NSString stringForByteSize:[[tableStatus objectForKey:@"Data_length"] longLongValue]]]];
[info addObject:[NSString stringWithFormat:NSLocalizedString(@"encoding: %@", @"encoding: %@"), [tableDataInstance tableEncoding]]];
@@ -142,7 +134,7 @@
}
}
-
+
// Get PROC/FUNC information
else if ([tableListInstance tableType] == SPTableTypeProc || [tableListInstance tableType] == SPTableTypeFunc) {
@@ -150,7 +142,7 @@
[info addObject:NSLocalizedString(@"PROCEDURE INFORMATION", @"header for procedure info pane")];
else
[info addObject:NSLocalizedString(@"FUNCTION INFORMATION", @"header for function info pane")];
-
+
if ([tableListInstance tableName]) {
// Retrieve the table status information via the data cache
@@ -171,7 +163,7 @@
// Check for 'LAST_ALTERED'
if (![[tableStatus objectForKey:@"LAST_ALTERED"] isNSNull]) {
-
+
// Add the update date to the infoTable
[info addObject:[NSString stringWithFormat:NSLocalizedString(@"updated: %@", @"updated: %@"), [self _getUserDefinedDateStringFromMySQLDate:[tableStatus objectForKey:@"LAST_ALTERED"]]]];
}
@@ -200,6 +192,57 @@
}
}
+ // Get VIEW information
+ else if ([tableListInstance tableType] == SPTableTypeView) {
+
+ [info addObject:NSLocalizedString(@"VIEW INFORMATION", @"header for view info pane")];
+
+ if ([tableListInstance tableName]) {
+
+ // Retrieve the table status information via the data cache
+ tableStatus = [tableDataInstance statusValues];
+
+ // Check for errors
+ if (![tableStatus count]) {
+ [info addObject:NSLocalizedString(@"error occurred", @"error occurred")];
+ return;
+ }
+
+ // Check for 'CREATED' == NULL
+ if (![[tableStatus objectForKey:@"DEFINER"] isNSNull]) {
+
+ // Add the creation date to the infoTable
+ [info addObject:[NSString stringWithFormat:NSLocalizedString(@"definer: %@", @"definer: %@"), [tableStatus objectForKey:@"DEFINER"]]];
+
+ // Check for 'SECURITY_TYPE'
+ if (![[tableStatus objectForKey:@"SECURITY_TYPE"] isNSNull]) {
+ [info addObject:[NSString stringWithFormat:NSLocalizedString(@"execution privilege: %@", @"execution privilege: %@"), [tableStatus objectForKey:@"SECURITY_TYPE"]]];
+ }
+
+ // Check for 'IS_UPDATABLE'
+ if (![[tableStatus objectForKey:@"IS_UPDATABLE"] isNSNull]) {
+ [info addObject:[NSString stringWithFormat:NSLocalizedString(@"is updatable: %@", @"is updatable: %@"), [tableStatus objectForKey:@"IS_UPDATABLE"]]];
+ }
+
+ // Check for 'CHECK_OPTION'
+ if (![[tableStatus objectForKey:@"CHECK_OPTION"] isNSNull]) {
+ [info addObject:[NSString stringWithFormat:NSLocalizedString(@"check option: %@", @"check option: %@"), [tableStatus objectForKey:@"CHECK_OPTION"]]];
+ }
+
+ // Check for 'CHARACTER_SET_CLIENT'
+ if (![[tableStatus objectForKey:@"CHARACTER_SET_CLIENT"] isNSNull]) {
+ [info addObject:[NSString stringWithFormat:NSLocalizedString(@"character set client: %@", @"character set client: %@"), [tableStatus objectForKey:@"CHARACTER_SET_CLIENT"]]];
+ }
+
+ // Check for 'COLLATION_CONNECTION'
+ if (![[tableStatus objectForKey:@"COLLATION_CONNECTION"] isNSNull]) {
+ [info addObject:[NSString stringWithFormat:NSLocalizedString(@"collation connection: %@", @"collation connection: %@"), [tableStatus objectForKey:@"COLLATION_CONNECTION"]]];
+ }
+
+ }
+ }
+
+ }
[infoTable reloadData];