From fc748400d92a0b7874a19eba3fa573cdf1415ee5 Mon Sep 17 00:00:00 2001 From: stuconnolly Date: Wed, 3 Jun 2009 20:46:57 +0000 Subject: Various enhancements to relation functionality, including: - Only presenting valid tables for possible relations, that is InnoDB tables. - Only presenting valid columns for possible relations, that is columns of the same data type. - Loads of interface validation. --- Interfaces/English.lproj/DBView.xib | 492 +++++++++++++++++------------------- Source/SPGrowlController.m | 10 +- Source/SPTableRelations.h | 50 ++-- Source/SPTableRelations.m | 396 +++++++++++++++-------------- 4 files changed, 468 insertions(+), 480 deletions(-) diff --git a/Interfaces/English.lproj/DBView.xib b/Interfaces/English.lproj/DBView.xib index ce9d94a3..8a31c76d 100644 --- a/Interfaces/English.lproj/DBView.xib +++ b/Interfaces/English.lproj/DBView.xib @@ -2,12 +2,14 @@ 1050 - 9G55 + 9J61 677 - 949.43 + 949.46 353.00 YES + + YES @@ -79,7 +81,6 @@ 4352 {212, 393} - YES @@ -176,7 +177,6 @@ {{1, 1}, {212, 393}} - @@ -192,7 +192,6 @@ -2147483392 {{175, 1}, {15, 481}} - _doScroller: 9.979253e-01 @@ -202,7 +201,6 @@ 256 {{-100, -100}, {141, 11}} - 257 _doScroller: @@ -211,7 +209,6 @@ {214, 395} - 530 @@ -234,7 +231,6 @@ 4352 {212, 123} - YES @@ -298,7 +294,6 @@ {{1, 1}, {212, 123}} - @@ -309,7 +304,6 @@ -2147483392 {{175, 1}, {15, 481}} - _doScroller: 9.979253e-01 @@ -319,7 +313,6 @@ 256 {{-100, -100}, {141, 11}} - 257 _doScroller: @@ -328,7 +321,6 @@ {{0, 404}, {214, 125}} - 530 @@ -339,14 +331,12 @@ {{-1, 22}, {214, 529}} - 292 {{0, -1}, {32, 25}} - YES -2080244224 @@ -375,7 +365,6 @@ 292 {{20, 0}, {46, 25}} - YES -2076049856 @@ -384,7 +373,7 @@ -2042609409 35 - + NSImage button_action @@ -399,7 +388,7 @@ 1048576 2147483647 - + NSImage button_action @@ -486,7 +475,6 @@ {{197, 0}, {15, 23}} - YES 130560 @@ -519,7 +507,6 @@ {{93, 0}, {104, 23}} - YES 130560 @@ -540,7 +527,6 @@ 292 {{61, -1}, {32, 25}} - YES -2080244224 @@ -563,7 +549,6 @@ {212, 550} - NSView @@ -576,7 +561,6 @@ 274 {{-7, -10}, {735, 564}} - YES @@ -601,7 +585,6 @@ 257 {{538, 4}, {61, 13}} - YES 68288064 @@ -622,7 +605,6 @@ 257 {{604, 2}, {79, 17}} - YES -1539178944 @@ -731,14 +713,12 @@ 4352 {688, 289} - YES 256 {688, 17} - @@ -746,7 +726,6 @@ -2147483392 {{-26, 0}, {16, 17}} - YES @@ -1279,7 +1258,6 @@ {{1, 17}, {688, 289}} - @@ -1290,7 +1268,6 @@ -2147483392 {{611, 17}, {15, 274}} - _doScroller: 9.858657e-01 @@ -1300,7 +1277,6 @@ -2147483392 {{1, 291}, {610, 15}} - 1 _doScroller: @@ -1315,7 +1291,6 @@ {{1, 0}, {688, 17}} - @@ -1325,7 +1300,6 @@ {{-1, 22}, {690, 307}} - 562 @@ -1340,7 +1314,6 @@ 292 {{-1, -1}, {32, 25}} - YES -1543373312 @@ -1362,7 +1335,6 @@ 292 {{93, -1}, {32, 25}} - YES -2080244224 @@ -1384,7 +1356,6 @@ 292 {{30, -1}, {32, 25}} - YES -1543373312 @@ -1409,7 +1380,6 @@ 292 {{61, -1}, {32, 25}} - YES -1543373312 @@ -1446,7 +1416,6 @@ {{125, 0}, {564, 23}} - YES 130560 @@ -1462,7 +1431,6 @@ {689, 329} - NSView @@ -1475,7 +1443,6 @@ 264 {{7, 183}, {46, 14}} - YES 67239424 @@ -1502,14 +1469,12 @@ 4352 {688, 141} - YES 256 {688, 17} - @@ -1517,7 +1482,6 @@ -2147483392 {{-26, 0}, {16, 17}} - YES @@ -1770,7 +1734,6 @@ {{1, 17}, {688, 141}} - @@ -1781,7 +1744,6 @@ -2147483392 {{611, 17}, {15, 126}} - _doScroller: 8.936170e-01 @@ -1791,7 +1753,6 @@ -2147483392 {{1, 143}, {610, 15}} - 1 _doScroller: @@ -1806,7 +1767,6 @@ {{1, 0}, {688, 17}} - @@ -1816,7 +1776,6 @@ {{-1, 22}, {690, 159}} - 562 @@ -1831,7 +1790,6 @@ 292 {{-1, -1}, {32, 25}} - YES -1543373312 @@ -1853,7 +1811,6 @@ 292 {{61, -1}, {32, 25}} - YES -2080244224 @@ -1875,7 +1832,6 @@ 292 {{30, -1}, {32, 25}} - YES -1543373312 @@ -1909,7 +1865,6 @@ {{670, 183}, {10, 13}} - YES 130560 @@ -1942,7 +1897,6 @@ {{93, 0}, {596, 23}} - YES 130560 @@ -1958,19 +1912,16 @@ {{0, 330}, {689, 201}} - NSView {{7, 10}, {689, 531}} - 2 {{10, 7}, {700, 544}} - Structure @@ -2992,7 +2943,7 @@ -2042609409 35 - + 400 @@ -3004,7 +2955,7 @@ 1048576 2147483647 - + _popUpItemAction: @@ -4432,20 +4383,17 @@ {{221, 0}, {723, 550}} - NSView {944, 550} - YES DBViewSplitter {944, 550} - {{0, 0}, {1440, 878}} {780, 502} @@ -9252,14 +9200,14 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 1 2 - {{196, 203}, {402, 307}} + {{196, 203}, {302, 307}} 1946157056 relationSheet - NSWindow + NSPanel {3.40282e+38, 3.40282e+38} - + 256 YES @@ -9276,7 +9224,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{120, 10}, {231, 22}} + {{80, 10}, {171, 22}} YES @@ -9341,12 +9289,12 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{-1, 15}, {119, 14}} + {{29, 15}, {49, 14}} YES 68288064 - 71435264 + 4326400 Column: @@ -9355,11 +9303,11 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 - {{1, 1}, {366, 40}} + {{1, 1}, {266, 40}} - {{17, 231}, {368, 56}} + {{17, 231}, {268, 56}} {0, 0} @@ -9392,7 +9340,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{120, 40}, {231, 22}} + {{81, 40}, {170, 22}} YES @@ -9477,7 +9425,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{120, 10}, {231, 22}} + {{81, 10}, {170, 22}} YES @@ -9562,13 +9510,13 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{0, 45}, {118, 14}} + {{15, 45}, {64, 14}} YES 68288064 - 71435264 - On Update: + 4326400 + On update: @@ -9578,13 +9526,13 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{0, 15}, {118, 14}} + {{19, 15}, {59, 14}} YES 68288064 - 71435264 - On Delete: + 4326400 + On delete: @@ -9592,11 +9540,11 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 - {{1, 1}, {366, 71}} + {{1, 1}, {266, 71}} - {{17, 49}, {368, 87}} + {{17, 49}, {268, 87}} {0, 0} @@ -9629,7 +9577,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{120, 40}, {231, 22}} + {{80, 40}, {171, 22}} YES @@ -9694,7 +9642,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{120, 10}, {231, 22}} + {{80, 10}, {171, 22}} YES @@ -9824,12 +9772,12 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{1, 45}, {117, 14}} + {{41, 45}, {37, 14}} YES 68288064 - 71435264 + 4326400 Table: @@ -9840,12 +9788,12 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{1, 15}, {117, 14}} + {{29, 15}, {49, 14}} YES 68288064 - 71435264 + 4326400 Column: @@ -9854,11 +9802,11 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 - {{1, 1}, {366, 71}} + {{1, 1}, {266, 71}} - {{17, 140}, {368, 87}} + {{17, 140}, {268, 87}} {0, 0} @@ -9881,7 +9829,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{291, 13}, {96, 28}} + {{191, 13}, {96, 28}} 1 YES @@ -9902,7 +9850,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 268 - {{195, 13}, {96, 28}} + {{97, 13}, {96, 28}} YES @@ -9920,7 +9868,8 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 - {402, 307} + {302, 307} + {{0, 0}, {1440, 878}} {3.40282e+38, 3.40282e+38} @@ -14988,30 +14937,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5540 - - - addRow: - - - - 5568 - - - - removeRow: - - - - 5569 - - - - removeButton - - - - 5571 - delegate @@ -15028,22 +14953,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5573 - - - relationsView - - - - 5574 - - - - refresh: - - - - 5575 - tableRelationsInstance @@ -15052,14 +14961,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5588 - - - labelText - - - - 5591 - tableDocumentInstance @@ -15084,14 +14985,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5595 - - - relationSheet - - - - 5598 - closeRelationSheet: @@ -15108,70 +15001,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5605 - - - columnSelect - - - - 5661 - - - - refTableSelect - - - - 5662 - - - - refColumnSelect - - - - 5663 - - - - onUpdateSelect - - - - 5664 - - - - onDeleteSelect - - - - 5665 - - - - addRelation: - - - - 5666 - - - - chooseRefTable: - - - - 5668 - - - - refreshButton - - - - 5669 - saveServerVariables: @@ -15308,22 +15137,6 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5706 - - - tableBox - - - - 5710 - - - - addButton - - - - 5711 - tableList @@ -15752,6 +15565,158 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 5901 + + + selectTableColumn: + + + + 5907 + + + + selectReferenceTable: + + + + 5908 + + + + addRelation: + + + + 5909 + + + + removeRelation: + + + + 5910 + + + + refreshRelations: + + + + 5911 + + + + confirmAddRelation: + + + + 5912 + + + + relationsTableView + + + + 5917 + + + + addRelationButton + + + + 5918 + + + + removeRelationButton + + + + 5919 + + + + refreshRelationsButton + + + + 5920 + + + + labelTextField + + + + 5921 + + + + addRelationPanel + + + + 5922 + + + + addRelationTableBox + + + + 5923 + + + + onDeletePopUpButton + + + + 5924 + + + + onUpdatePopUpButton + + + + 5925 + + + + refColumnPopUpButton + + + + 5926 + + + + refTablePopUpButton + + + + 5927 + + + + columnPopUpButton + + + + 5928 + + + + confirmAddRelationButton + + + + 5929 + @@ -24997,8 +24962,8 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{177, 216}, {944, 550}} - {{177, 216}, {944, 550}} + {{310, 234}, {944, 550}} + {{310, 234}, {944, 550}} {{62, 352}, {845, 504}} @@ -25392,15 +25357,20 @@ aGUgYWN0aXZlIHNlbGVjdGlvbiAo4oyl4oyYUik com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{525, 252}, {402, 307}} - {{525, 252}, {402, 307}} + {{847, 374}, {302, 307}} + {{847, 374}, {302, 307}} com.apple.InterfaceBuilder.CocoaPlugin YES - 1.330000e+02 + 9.200000e+01 + 0 + + + + 2.660000e+02 0 @@ -25852,7 +25822,7 @@ Y2hhbmdlIHRoZSBvcmRlcg - 5906 + 5929 @@ -26373,11 +26343,12 @@ Y2hhbmdlIHRoZSBvcmRlcg YES addRelation: - addRow: - chooseRefTable: closeRelationSheet: - refresh: - removeRow: + confirmAddRelation: + refreshRelations: + removeRelation: + selectReferenceTable: + selectTableColumn: YES @@ -26387,24 +26358,26 @@ Y2hhbmdlIHRoZSBvcmRlcg id id id + id YES YES - addButton - columnSelect - labelText - onDeleteSelect - onUpdateSelect - refColumnSelect - refTableSelect - refreshButton - relationSheet - relationsView - removeButton - tableBox + addRelationButton + addRelationPanel + addRelationTableBox + columnPopUpButton + confirmAddRelationButton + labelTextField + onDeletePopUpButton + onUpdatePopUpButton + refColumnPopUpButton + refTablePopUpButton + refreshRelationsButton + relationsTableView + removeRelationButton tableDataInstance tableDocumentInstance tableList @@ -26413,18 +26386,19 @@ Y2hhbmdlIHRoZSBvcmRlcg YES - id - id - id - id - id - id - id - id - id - id - id - id + NSButton + NSPanel + NSBox + NSPopUpButton + NSButton + NSTextField + NSPopUpButton + NSPopUpButton + NSPopUpButton + NSPopUpButton + NSButton + NSTableView + NSButton id id id diff --git a/Source/SPGrowlController.m b/Source/SPGrowlController.m index d65b5201..13e1698a 100644 --- a/Source/SPGrowlController.m +++ b/Source/SPGrowlController.m @@ -29,7 +29,7 @@ static SPGrowlController *sharedGrowlController = nil; @implementation SPGrowlController -/* +/** * Returns the shared Growl controller. */ + (SPGrowlController *)sharedGrowlController @@ -58,14 +58,14 @@ static SPGrowlController *sharedGrowlController = nil; - (id)init { - if (self = [super init]) { + if ((self = [super init])) { [GrowlApplicationBridge setGrowlDelegate:self]; } return self; } -/* +/** * The following base protocol methods are implemented to ensure the singleton status of this class. */ @@ -79,7 +79,7 @@ static SPGrowlController *sharedGrowlController = nil; - (void)release { } -/* +/** * Posts a Growl notification using the supplied details and default values. */ - (void)notifyWithTitle:(NSString *)title description:(NSString *)description notificationName:(NSString *)name @@ -93,7 +93,7 @@ static SPGrowlController *sharedGrowlController = nil; clickContext:nil]; } -/* +/** * Posts a Growl notification using the supplied details and effectively ignoring the default values. */ - (void)notifyWithTitle:(NSString *)title description:(NSString *)description notificationName:(NSString *)name iconData:(NSData *)data priority:(int)priority isSticky:(BOOL)sticky clickContext:(id)clickContext diff --git a/Source/SPTableRelations.h b/Source/SPTableRelations.h index bc1cf1fa..72806b77 100644 --- a/Source/SPTableRelations.h +++ b/Source/SPTableRelations.h @@ -31,39 +31,41 @@ @interface SPTableRelations : NSObject { IBOutlet id tableDocumentInstance; - IBOutlet id tablesListInstance; + IBOutlet id tablesListInstance; + IBOutlet id tableDataInstance; + IBOutlet id tableList; IBOutlet id tableWindow; - IBOutlet id tableDataInstance; - IBOutlet id addButton; - IBOutlet id removeButton; - IBOutlet id refreshButton; - IBOutlet id labelText; - IBOutlet id relationsView; - IBOutlet id relationSheet; + + IBOutlet NSButton *addRelationButton; + IBOutlet NSButton *removeRelationButton; + IBOutlet NSButton *refreshRelationsButton; + IBOutlet NSTextField *labelTextField; + IBOutlet NSTableView *relationsTableView; + IBOutlet NSPanel *addRelationPanel; - IBOutlet id tableBox; - IBOutlet id columnSelect; - IBOutlet id refTableSelect; - IBOutlet id refColumnSelect; - IBOutlet id onUpdateSelect; - IBOutlet id onDeleteSelect; + IBOutlet NSBox *addRelationTableBox; + IBOutlet NSPopUpButton *columnPopUpButton; + IBOutlet NSPopUpButton *refTablePopUpButton; + IBOutlet NSPopUpButton *refColumnPopUpButton; + IBOutlet NSPopUpButton *onUpdatePopUpButton; + IBOutlet NSPopUpButton *onDeletePopUpButton; + IBOutlet NSButton *confirmAddRelationButton; - CMMCPConnection *mySQLConnection; + CMMCPConnection *connection; - NSMutableArray *relData; + NSMutableArray *relationData; } -- (void)setConnection:(CMMCPConnection *)theConnection; +@property (readwrite, assign) CMMCPConnection *connection; // IB action methods -- (IBAction)addRow:(id)sender; -- (IBAction)removeRow:(id)sender; -- (IBAction)closeRelationSheet:(id)sender; - (IBAction)addRelation:(id)sender; -- (IBAction)chooseRefTable:(id)sender; -- (IBAction)refresh:(id)sender; - -- (void)tableChanged:(NSNotification *)notification; +- (IBAction)removeRelation:(id)sender; +- (IBAction)closeRelationSheet:(id)sender; +- (IBAction)confirmAddRelation:(id)sender; +- (IBAction)selectTableColumn:(id)sender; +- (IBAction)selectReferenceTable:(id)sender; +- (IBAction)refreshRelations:(id)sender; @end diff --git a/Source/SPTableRelations.m b/Source/SPTableRelations.m index 35ce0ec7..a08639f9 100644 --- a/Source/SPTableRelations.m +++ b/Source/SPTableRelations.m @@ -29,59 +29,46 @@ #import "CMMCPConnection.h" #import "CMMCPResult.h" #import "SPTableData.h" +#import "SPStringAdditions.h" + +@interface SPTableRelations (PrivateAPI) + +- (void)_updateAvailableTableColumns; + +@end @implementation SPTableRelations -/* +@synthesize connection; + +/** * init */ - (id)init { - if (![super init]) - return nil; - - relData = [[NSMutableArray alloc] init]; + if ((self = [super init])) { + relationData = [[NSMutableArray alloc] init]; + } return self; } -/* - * dealloc - */ -- (void)dealloc -{ - [relData release], relData = nil; - - [super dealloc]; -} - -/* - * awakeFromNib +/** + * Register to listen for table selection changes upon nib awakening. */ - (void)awakeFromNib { [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(tableChanged:) + selector:@selector(tableSelectionChanged:) name:NSTableViewSelectionDidChangeNotification object:tableList]; } -/* - * setConnection - * set the database connection - */ -- (void)setConnection:(CMMCPConnection *)theConnection -{ - // Weak reference - mySQLConnection = theConnection; -} - #pragma mark - #pragma mark IB action methods -/* - * closeRelationSheet - * happens if the user hits cancel +/** + * Closes the relation sheet. */ - (IBAction)closeRelationSheet:(id)sender { @@ -89,162 +76,155 @@ [NSApp stopModalWithCode:0]; } -/* - * addRelation - * attempt to add the relations from the relationSheet data +/** + * Add a new relation using the selected values. */ -- (IBAction)addRelation:(id)sender -{ - // 0 = success - int retCode = 0; - NSString *thisTable = [tablesListInstance tableName]; - NSString *thisColumn = [columnSelect titleOfSelectedItem]; - NSString *thatTable = [refTableSelect titleOfSelectedItem]; - NSString *thatColumn = [refColumnSelect titleOfSelectedItem]; - NSString *onUpdate = [onUpdateSelect titleOfSelectedItem]; - NSString *onDelete = [onDeleteSelect titleOfSelectedItem]; - NSString *query = [NSString stringWithFormat: - @"ALTER TABLE `%@` ADD FOREIGN KEY (`%@`) REFERENCES `%@` (`%@`)", - thisTable, - thisColumn, - thatTable, - thatColumn]; +- (IBAction)confirmAddRelation:(id)sender +{ + NSString *thisTable = [tablesListInstance tableName]; + NSString *thisColumn = [columnPopUpButton titleOfSelectedItem]; + NSString *thatTable = [refTablePopUpButton titleOfSelectedItem]; + NSString *thatColumn = [refColumnPopUpButton titleOfSelectedItem]; + + NSString *query = [NSString stringWithFormat:@"ALTER TABLE %@ ADD FOREIGN KEY (%@) REFERENCES %@ (%@)", + [thisTable backtickQuotedString], + thisColumn, + [thatTable backtickQuotedString], + thatColumn]; - if( [onDelete length] ) { - query = [query stringByAppendingString:[NSString stringWithFormat:@" ON DELETE %@", onDelete]]; + // If required add ON DELETE + if ([onDeletePopUpButton indexOfSelectedItem] > 0) { + query = [query stringByAppendingString:[NSString stringWithFormat:@" ON DELETE %@", [onDeletePopUpButton titleOfSelectedItem]]]; } - if( [onUpdate length] ) { - query = [query stringByAppendingString:[NSString stringWithFormat:@" ON UPDATE %@", onUpdate]]; + + // If required add ON UPDATE + if ([onUpdatePopUpButton indexOfSelectedItem] > 0) { + query = [query stringByAppendingString:[NSString stringWithFormat:@" ON UPDATE %@", [onUpdatePopUpButton titleOfSelectedItem]]]; } - [mySQLConnection queryString:query]; + // Execute query + [connection queryString:query]; - if ( ! [[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) { - NSLog(@"error: %@", [mySQLConnection getLastErrorMessage]); - retCode = 1; - } + int retCode = (![[connection getLastErrorMessage] isEqualToString:@""]); [NSApp stopModalWithCode:retCode]; } -/* - * chooseRefTable - * update the columns select when the user chooses a reference table +/** + * Updates the available columns when the user selects a table. */ -- (IBAction)chooseRefTable:(id)sender +- (IBAction)selectTableColumn:(id)sender { - NSString *table = [refTableSelect titleOfSelectedItem]; - - [refColumnSelect removeAllItems]; - - NSDictionary *info = [tableDataInstance informationForTable:table]; - NSArray *cols = [info objectForKey:@"columns"]; - NSMutableArray *colNames = [[NSMutableArray alloc] init]; - // TODO depending on the selected column type, it would be smart to only - // show columns that are valid to linkage. this.int -> ints only - for( int i = 0; i < [cols count]; i++ ) { - [colNames addObject:[[cols objectAtIndex:i] objectForKey:@"name"]]; - } - [refColumnSelect addItemsWithTitles:colNames]; - [colNames release]; + [self _updateAvailableTableColumns]; } -/* - * addRow - * called when the user indicated they want to add a relation +/** + * Updates the available columns when the user selects a table. */ -- (IBAction)addRow:(id)sender +- (IBAction)selectReferenceTable:(id)sender { - // TODO check that this is an INNO table + [self _updateAvailableTableColumns]; +} + +/** + * Called whenever the user selected to add a new relation. + */ +- (IBAction)addRelation:(id)sender +{ + // Set up the controls + [addRelationTableBox setTitle:[NSString stringWithFormat:@"Table: %@", [tablesListInstance tableName]]]; - // set up the controls - [tableBox setTitle:[NSString stringWithFormat:@"Table: %@",[tablesListInstance tableName] ]]; - [columnSelect removeAllItems]; - [columnSelect addItemsWithTitles:[tableDataInstance columnNames]]; - [refTableSelect removeAllItems]; - // grab only real tables - // TODO filter this so it only shows INNO tables - NSArray *tables = [tablesListInstance tables]; - NSArray *types = [tablesListInstance tableTypes]; - NSMutableArray *validTables = [[NSMutableArray alloc] init]; - for( int i = 0; i < [tables count]; i++ ) { - if( [[types objectAtIndex:i] intValue] == SP_TABLETYPE_TABLE ) { - [validTables addObject:[tables objectAtIndex:i]]; - } + [columnPopUpButton removeAllItems]; + [columnPopUpButton addItemsWithTitles:[tableDataInstance columnNames]]; + + [refTablePopUpButton removeAllItems]; + + // Get all InnoDB tables in the current database + CMMCPResult *result = [connection queryString:[NSString stringWithFormat:@"SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND engine = 'InnoDB' AND table_schema = '%@' AND table_name != '%@'", [tableDocumentInstance database], [tablesListInstance tableName]]]; + + [result dataSeek:0]; + + for (int i = 0; i < [result numOfRows]; i++) + { + [refTablePopUpButton addItemWithTitle:[[result fetchRowAsArray] objectAtIndex:0]]; } - [refTableSelect addItemsWithTitles:validTables]; - [validTables release]; - [self chooseRefTable:nil]; - [NSApp beginSheet:relationSheet - modalForWindow:tableWindow - modalDelegate:self - didEndSelector:nil - contextInfo:nil]; + [self selectReferenceTable:nil]; + [NSApp beginSheet:addRelationPanel + modalForWindow:tableWindow + modalDelegate:self + didEndSelector:nil + contextInfo:nil]; - int code = [NSApp runModalForWindow:relationSheet]; + int code = [NSApp runModalForWindow:addRelationPanel]; - [NSApp endSheet:relationSheet]; - [relationSheet orderOut:nil]; + [NSApp endSheet:addRelationPanel]; + [addRelationPanel orderOut:nil]; // 0 indicates success - if( code ) { + if (code) { NSBeginAlertSheet(NSLocalizedString(@"Error creating relation", @"error creating relation message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], nil, nil, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"The specified relation was unable to be created.\n\nMySQL said: %@", @"error creating relation informative message"), [mySQLConnection getLastErrorMessage]]); - } else { - [self refresh:nil]; + [NSString stringWithFormat:NSLocalizedString(@"The specified relation was unable to be created.\n\nMySQL said: %@", @"error creating relation informative message"), [connection getLastErrorMessage]]); + } + else { + [self refreshRelations:nil]; } } -/* - * removeRow - * called when rows are selected and the user wants to remove those relations +/** + * Removes the selected relations. */ -- (IBAction)removeRow:(id)sender +- (IBAction)removeRelation:(id)sender { - if ( [relationsView numberOfSelectedRows] ) { - int resp = NSRunAlertPanel(NSLocalizedString(@"Delete relation", @"delete relation message"), - NSLocalizedString(@"Are you sure you want to delete the selected relations? This action cannot be undone", @"delete selected relation informative message"), - NSLocalizedString(@"Delete", @"delete button"), - NSLocalizedString(@"Cancel", @"cancel button"), nil ); + if ([relationsTableView numberOfSelectedRows] > 0) { + + int response = NSRunAlertPanel(NSLocalizedString(@"Delete relation", @"delete relation message"), + NSLocalizedString(@"Are you sure you want to delete the selected relations? This action cannot be undone", @"delete selected relation informative message"), + NSLocalizedString(@"Delete", @"delete button"), + NSLocalizedString(@"Cancel", @"cancel button"), nil ); - if( resp == NSAlertDefaultReturn ) { + if (response == NSAlertDefaultReturn) { + NSString *thisTable = [tablesListInstance tableName]; - NSIndexSet *selectedSet = [relationsView selectedRowIndexes]; + NSIndexSet *selectedSet = [relationsTableView selectedRowIndexes]; + unsigned int row = [selectedSet lastIndex]; - while( row != NSNotFound ) + + while (row != NSNotFound) { - NSArray *relName = [[relData objectAtIndex:row] objectForKey:@"name"]; - NSString *query = [NSString stringWithFormat:@"ALTER TABLE `%@` DROP FOREIGN KEY `%@`", thisTable, relName]; + NSString *relationName = [[relationData objectAtIndex:row] objectForKey:@"name"]; + NSString *query = [NSString stringWithFormat:@"ALTER TABLE %@ DROP FOREIGN KEY %@", [thisTable backtickQuotedString], [relationName backtickQuotedString]]; - [mySQLConnection queryString:query]; + [connection queryString:query]; - if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) { + if (![[connection getLastErrorMessage] isEqualToString:@""] ) { NSBeginAlertSheet(NSLocalizedString(@"Unable to remove relation", @"error removing relation message"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], nil, nil, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"The selected relation couldn't be removed.\n\nMySQL said: %@", @"error removing relation informative message"), [mySQLConnection getLastErrorMessage]]); - // abort loop + [NSString stringWithFormat:NSLocalizedString(@"The selected relation couldn't be removed.\n\nMySQL said: %@", @"error removing relation informative message"), [connection getLastErrorMessage]]); + + // Abort loop break; } + row = [selectedSet indexLessThanIndex:row]; } - [self refresh:nil]; + + [self refreshRelations:nil]; } } } -/* - * refresh - * called to refesh the relations list +/** + * Refreshes the displayed relations. */ -- (IBAction)refresh:(id)sender +- (IBAction)refreshRelations:(id)sender { - [relData removeAllObjects]; + [relationData removeAllObjects]; if ([tablesListInstance tableType] == SP_TABLETYPE_TABLE) { @@ -252,32 +232,33 @@ NSArray *constraints = [tableDataInstance getConstraints]; - for( int i = 0; i < [constraints count]; i++ ) { - [relData addObject:[NSDictionary dictionaryWithObjectsAndKeys: - [tablesListInstance tableName], @"table", - [[constraints objectAtIndex:i] objectForKey:@"name"], @"name", - [[constraints objectAtIndex:i] objectForKey:@"columns"], @"columns", - [[constraints objectAtIndex:i] objectForKey:@"ref_table"], @"fk_table", - [[constraints objectAtIndex:i] objectForKey:@"ref_columns"], @"fk_columns", - [[constraints objectAtIndex:i] objectForKey:@"update"], @"on_update", - [[constraints objectAtIndex:i] objectForKey:@"delete"], @"on_delete", - nil]]; + for (NSDictionary *constraint in constraints) + { + [relationData addObject:[NSDictionary dictionaryWithObjectsAndKeys: + [tablesListInstance tableName], @"table", + [constraint objectForKey:@"name"], @"name", + [constraint objectForKey:@"columns"], @"columns", + [constraint objectForKey:@"ref_table"], @"fk_table", + [constraint objectForKey:@"ref_columns"], @"fk_columns", + [constraint objectForKey:@"update"], @"on_update", + [constraint objectForKey:@"delete"], @"on_delete", + nil]]; } } - [relationsView reloadData]; + [relationsTableView reloadData]; } -/* - * tableChanged - * notification from the tableList when the users click a table +/** + * Called whenever the user selects a different table. */ -- (void)tableChanged:(NSNotification *)notification +- (void)tableSelectionChanged:(NSNotification *)notification { // To begin enable all interface elements - [addButton setEnabled:YES]; - [refreshButton setEnabled:YES]; + [addRelationButton setEnabled:YES]; + [refreshRelationsButton setEnabled:YES]; + [relationsTableView setEnabled:YES]; // Get the current table's storage engine NSString *engine = [tableDataInstance statusValueForKey:@"Engine"]; @@ -285,76 +266,107 @@ if (([tablesListInstance tableType] == SP_TABLETYPE_TABLE) && ([[engine lowercaseString] isEqualToString:@"innodb"])) { // Update the text label - [labelText setStringValue:[NSString stringWithFormat:@"Relations for table: %@", [tablesListInstance tableName]]]; + [labelTextField setStringValue:[NSString stringWithFormat:@"Relations for table: %@", [tablesListInstance tableName]]]; - [addButton setEnabled:YES]; - [refreshButton setEnabled:YES]; + [addRelationButton setEnabled:YES]; + [refreshRelationsButton setEnabled:YES]; + [relationsTableView setEnabled:YES]; } else { - [addButton setEnabled:NO]; - [refreshButton setEnabled:NO]; + [addRelationButton setEnabled:NO]; + [refreshRelationsButton setEnabled:NO]; + [relationsTableView setEnabled:NO]; - [labelText setStringValue:([tablesListInstance tableType] == SP_TABLETYPE_TABLE) ? @"This table does not support relations" : @""]; + [labelTextField setStringValue:([tablesListInstance tableType] == SP_TABLETYPE_TABLE) ? @"This table does not support relations" : @""]; } - [self refresh:self]; + [self refreshRelations:self]; } #pragma mark - #pragma mark Tableview datasource methods -- (int)numberOfRowsInTableView:(NSTableView *)aTableView +- (int)numberOfRowsInTableView:(NSTableView *)tableView { - return [relData count]; + return [relationData count]; } -- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn - row:(int)rowIndex +- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)rowIndex { - return [[relData objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]]; -} - -- (void)tableView:(NSTableView *)aTableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex -{ - + return [[relationData objectAtIndex:rowIndex] objectForKey:[tableColumn identifier]]; } #pragma mark - #pragma mark Tableview delegate methods -- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn -{ - -} - -- (void)tableViewSelectionDidChange:(NSNotification *)aNotification +/** + * Called whenever the relations table view selection changes. + */ +- (void)tableViewSelectionDidChange:(NSNotification *)notification { - [removeButton setEnabled:([relationsView numberOfSelectedRows] > 0)]; + [removeRelationButton setEnabled:([relationsTableView numberOfSelectedRows] > 0)]; } -- (void)tableViewSelectionIsChanging:(NSNotification *)aNotification -{ - -} +#pragma mark - +#pragma mark Other -- (void)tableViewColumnDidResize:(NSNotification *)aNotification -{ +/* + * Dealloc. + */ +- (void)dealloc +{ + [relationData release], relationData = nil; + [super dealloc]; } -- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex -{ - return NO; -} +@end -- (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard -{ - return NO; -} +@implementation SPTableRelations (PrivateAPI) -- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command +/** + * Updates the available table columns that the reference is pointing to. Available columns are those that are + * within the selected table and are of the same data type as the column the reference is from. + */ +- (void)_updateAvailableTableColumns { - return NO; + NSString *column = [columnPopUpButton titleOfSelectedItem]; + NSString *table = [refTablePopUpButton titleOfSelectedItem]; + + [tableDataInstance resetAllData]; + [tableDataInstance updateInformationForCurrentTable]; + + NSDictionary *columnInfo = [[tableDataInstance columnWithName:column] copy]; + + [refColumnPopUpButton setEnabled:NO]; + [confirmAddRelationButton setEnabled:NO]; + + [refColumnPopUpButton removeAllItems]; + + [tableDataInstance resetAllData]; + NSDictionary *tableInfo = [tableDataInstance informationForTable:table]; + + NSArray *columns = [tableInfo objectForKey:@"columns"]; + + NSMutableArray *validColumns = [NSMutableArray array]; + + // Only add columns of the same data type + for (int i = 0; i < [columns count]; i++) + { + if ([[columnInfo objectForKey:@"type"] isEqualToString:[[columns objectAtIndex:i] objectForKey:@"type"]]) { + [validColumns addObject:[[columns objectAtIndex:i] objectForKey:@"name"]]; + } + } + + // Add the valid columns + if ([validColumns count] > 0) { + [refColumnPopUpButton addItemsWithTitles:validColumns]; + + [refColumnPopUpButton setEnabled:YES]; + [confirmAddRelationButton setEnabled:YES]; + } + + [columnInfo release]; } @end -- cgit v1.2.3