aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPTableRelations.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPTableRelations.m')
-rw-r--r--Source/SPTableRelations.m363
1 files changed, 363 insertions, 0 deletions
diff --git a/Source/SPTableRelations.m b/Source/SPTableRelations.m
new file mode 100644
index 00000000..62ca6582
--- /dev/null
+++ b/Source/SPTableRelations.m
@@ -0,0 +1,363 @@
+//
+// SPTableRelations.h
+// sequel-pro
+//
+// Created by J Knight on 13/05/09.
+// Copyright 2009 J Knight. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+//
+
+#import "SPTableRelations.h"
+#import "TableDocument.h"
+#import "TablesList.h"
+#import "CMMCPConnection.h"
+#import "CMMCPResult.h"
+#import "SPTableData.h"
+
+@implementation SPTableRelations
+
+/*
+ * init
+ */
+- (id)init
+{
+ if (![super init])
+ return nil;
+
+ relData = [[NSMutableArray alloc] init];
+
+ return self;
+}
+
+/*
+ * dealloc
+ */
+- (void)dealloc
+{
+ [relData release], relData = nil;
+
+ [super dealloc];
+}
+
+/*
+ * awakeFromNib
+ */
+- (void)awakeFromNib
+{
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(tableChanged:)
+ name:NSTableViewSelectionDidChangeNotification
+ object:tableList];
+}
+
+/*
+ * setConnection
+ * set the database connection
+ */
+- (void)setConnection:(CMMCPConnection *)theConnection
+{
+ mySQLConnection = theConnection;
+}
+
+#pragma mark -
+#pragma mark IB action methods
+
+/*
+ * closeRelationSheet
+ * happens if the user hits cancel
+ */
+- (IBAction)closeRelationSheet:(id)sender
+{
+ // 0 = success,
+ [NSApp stopModalWithCode:0];
+}
+
+/*
+ * addRelation
+ * attempt to add the relations from the relationSheet data
+ */
+- (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];
+
+ if( [onDelete length] ) {
+ query = [query stringByAppendingString:[NSString stringWithFormat:@" ON DELETE %@", onDelete]];
+ }
+ if( [onUpdate length] ) {
+ query = [query stringByAppendingString:[NSString stringWithFormat:@" ON UPDATE %@", onUpdate]];
+ }
+
+ //NSLog( query );
+
+ [mySQLConnection queryString:query];
+
+ if ( ! [[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) {
+ NSLog(@"error: %@", [mySQLConnection getLastErrorMessage]);
+ retCode = 1;
+ }
+
+ [NSApp stopModalWithCode:retCode];
+}
+
+/*
+ * chooseRefTable
+ * update the columns select when the user chooses a reference table
+ */
+- (IBAction)chooseRefTable:(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];
+}
+
+/*
+ * addRow
+ * called when the user indicated they want to add a relation
+ */
+- (IBAction)addRow:(id)sender
+{
+ // TODO check that this is an INNO table
+
+ // 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]];
+ }
+ }
+ [refTableSelect addItemsWithTitles:validTables];
+ [validTables release];
+ [self chooseRefTable:nil];
+
+ [NSApp beginSheet:relationSheet
+ modalForWindow:tableWindow
+ modalDelegate:self
+ didEndSelector:nil
+ contextInfo:nil];
+
+
+ int code = [NSApp runModalForWindow:relationSheet];
+
+ [NSApp endSheet:relationSheet];
+ [relationSheet orderOut:nil];
+
+ // 0 indicates success
+ if( code ) {
+ NSRunAlertPanel(NSLocalizedString(@"Error", @"error"), //@"Error Adding Relation",
+ [NSString stringWithFormat:NSLocalizedString(@"Couldn't add relation.\nMySQL said: %@",@"message of panel when relation cannot be created"),[mySQLConnection getLastErrorMessage]],
+ NSLocalizedString(@"OK", @"OK button"), nil, nil );
+ } else {
+ [self refresh:nil];
+ }
+}
+
+/*
+ * removeRow
+ * called when rows are selected and the user wants to remove those relations
+ */
+- (IBAction)removeRow:(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?\nThis action cannot be undone!",@"delete selected relation informative message"),
+ NSLocalizedString(@"Delete", @"delete button"),
+ NSLocalizedString(@"Cancel", @"cancel button"), nil );
+ if( resp == NSAlertDefaultReturn ) {
+ NSString *thisTable = [tablesListInstance tableName];
+ NSIndexSet *selectedSet = [relationsView selectedRowIndexes];
+ unsigned int row = [selectedSet lastIndex];
+ while( row != NSNotFound ) {
+ NSArray *relName = [[relData objectAtIndex:row] objectForKey:@"name"];
+ NSString *query = [NSString stringWithFormat:@"ALTER TABLE `%@` DROP FOREIGN KEY `%@`",
+ thisTable, relName];
+ //NSLog( query );
+
+ [mySQLConnection queryString:query];
+
+ if ( ! [[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) {
+ NSLog(@"error: %@", [mySQLConnection getLastErrorMessage]);
+ NSRunAlertPanel(NSLocalizedString(@"Error", @"error"),
+ [NSString stringWithFormat:NSLocalizedString(@"Couldn't remove relation.\nMySQL said: %@",@"message of panel when relation cannot be removed"),[mySQLConnection getLastErrorMessage]],
+ NSLocalizedString(@"OK", @"OK button"), nil, nil );
+ // abort loop
+ break;
+ }
+ row = [selectedSet indexLessThanIndex:row];
+ }
+ [self refresh:nil];
+ }
+ }
+}
+
+/*
+ * refresh
+ * called to refesh the relations list
+ */
+- (IBAction)refresh:(id)sender
+{
+ [relData removeAllObjects];
+
+ if([tablesListInstance tableType] == SP_TABLETYPE_TABLE) {
+ // update the top label
+ [labelText setStringValue:[NSString stringWithFormat:@"Relations for table: %@",[tablesListInstance tableName]]];
+
+ [tableDataInstance updateInformationForCurrentTable];
+
+ 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]];
+
+ }
+ }
+
+ [relationsView reloadData];
+}
+
+/*
+ * tableChanged
+ * notification from the tableList when the users click a table
+ */
+- (void)tableChanged:(NSNotification *)notification
+{
+ // To begin enable all interface elements
+ [addButton setEnabled:YES];
+ [refreshButton setEnabled:YES];
+
+ // Get the current table's storage engine
+ NSString *engine = [tableDataInstance statusValueForKey:@"Engine"];
+
+ if (([tablesListInstance tableType] == SP_TABLETYPE_TABLE) && ([[engine lowercaseString] isEqualToString:@"innodb"])) {
+ [addButton setEnabled:YES];
+ [refreshButton setEnabled:YES];
+
+ [self refresh:self];
+ } else {
+ [addButton setEnabled:NO];
+ [refreshButton setEnabled:NO];
+
+ [labelText setStringValue:([tablesListInstance tableType] == SP_TABLETYPE_TABLE) ? @"This table does not support relations" : @""];
+ }
+}
+
+#pragma mark -
+#pragma mark Tableview datasource methods
+
+- (int)numberOfRowsInTableView:(NSTableView *)aTableView
+{
+ return [relData count];
+}
+
+- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn
+ row:(int)rowIndex
+{
+ NSDictionary *theRow = [relData objectAtIndex:rowIndex];
+ return [theRow objectForKey:[aTableColumn identifier]];
+}
+
+- (void)tableView:(NSTableView *)aTableView
+ setObjectValue:(id)anObject
+ forTableColumn:(NSTableColumn *)aTableColumn
+ row:(int)rowIndex
+{
+
+}
+
+#pragma mark -
+#pragma mark Tableview delegate methods
+
+- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn *)tableColumn
+{
+
+}
+
+- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
+{
+ if ( [relationsView numberOfSelectedRows] ) {
+ [removeButton setEnabled:YES];
+ } else {
+ [removeButton setEnabled:NO];
+ }
+}
+
+- (void)tableViewSelectionIsChanging:(NSNotification *)aNotification
+{
+
+}
+
+- (void)tableViewColumnDidResize:(NSNotification *)aNotification
+{
+
+}
+
+- (BOOL)tableView:(NSTableView *)aTableView shouldEditTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
+{
+ return NO;
+}
+
+- (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
+{
+ return NO;
+}
+
+- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command
+{
+ return NO;
+}
+
+@end