Permalink
Browse files

Fix a popular exception when a user tried to edit a field with a lost…

… connection and then chose "disconnect" when Sequel Pro asks to reconnect (attempt at #2137)
  • Loading branch information...
dmoagx committed Jun 11, 2015
1 parent f6be61c commit 197b057a443153bfe7c9817b9b3edd7caeaabe78
Showing with 51 additions and 29 deletions.
  1. +3 −2 Source/SPCopyTable.m
  2. +47 −26 Source/SPTableContent.m
  3. +1 −1 Source/SPTableContentDelegate.m
View
@@ -495,8 +495,9 @@ - (NSString *)rowsAsSqlInsertsOnlySelectedRows:(BOOL)onlySelected
// If the data is not loaded, attempt to fetch the value
if ([cellData isSPNotLoaded] && [[self delegate] isKindOfClass:spTableContentClass]) {
NSString *whereArgument = [tableInstance argumentForRow:rowIndex];
// Abort if no table name given, not table content, or if there are no indices on this table
if (!selectedTable || ![[self delegate] isKindOfClass:spTableContentClass] || ![(NSString*)[tableInstance argumentForRow:rowIndex] length]) {
if (!selectedTable || ![[self delegate] isKindOfClass:spTableContentClass] || ![whereArgument length]) {
NSBeep();
free(columnMappings);
free(columnTypes);
@@ -509,7 +510,7 @@ - (NSString *)rowsAsSqlInsertsOnlySelectedRows:(BOOL)onlySelected
[NSString stringWithFormat:@"SELECT %@ FROM %@ WHERE %@",
[NSArrayObjectAtIndex(tbHeader, columnMappings[c]) backtickQuotedString],
[selectedTable backtickQuotedString],
[tableInstance argumentForRow:rowIndex]]];
whereArgument]];
}
// Check for NULL value
View
@@ -1884,12 +1884,13 @@ - (IBAction)duplicateRow:(id)sender
if ([prefs boolForKey:SPLoadBlobsAsNeeded]) {
// Abort if there are no indices on this table - argumentForRow will display an error.
if (![[self argumentForRow:[tableContentView selectedRow]] length]) {
NSString *whereArgument = [self argumentForRow:[tableContentView selectedRow]];
if (![whereArgument length]) {
return;
}
// If we have indexes, use argumentForRow
queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", [selectedTable backtickQuotedString], [self argumentForRow:[tableContentView selectedRow]]]];
queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", [selectedTable backtickQuotedString], whereArgument]];
dbDataRow = [queryResult getRowAsArray];
}
#endif
@@ -2203,9 +2204,14 @@ - (void)removeRowSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode c
while (anIndex != NSNotFound) {
// Build the AND clause of PRIMARY KEYS
[deleteQuery appendString:@"("];
[deleteQuery appendString:[self argumentForRow:anIndex excludingLimits:YES]];
[deleteQuery appendString:@")"];
NSString *whereArg = [self argumentForRow:anIndex excludingLimits:YES];
if(![whereArg length]) {
SPLog(@"empty WHERE clause not acceptable for DELETE! Abort.");
NSBeep();
return;
}
[deleteQuery appendFormat:@"(%@)",whereArg];
// Split deletion query into 64k chunks
if([deleteQuery length] > 64000) {
@@ -2825,7 +2831,15 @@ - (BOOL)saveRowToTable
[queryString appendFormat:@"%@ = %@",
[NSArrayObjectAtIndex(rowFieldsToSave, i) backtickQuotedString], NSArrayObjectAtIndex(rowValuesToSave, i)];
}
[queryString appendFormat:@" WHERE %@", [self argumentForRow:-2]];
NSString *whereArg = [self argumentForRow:-2];
if(![whereArg length]) {
SPLog(@"Did not find plausible WHERE condition for UPDATE.");
NSBeep();
[rowFieldsToSave release];
[rowValuesToSave release];
return NO;
}
[queryString appendFormat:@" WHERE %@", whereArg];
}
[rowFieldsToSave release];
@@ -3029,25 +3043,22 @@ - (NSString *)argumentForRow:(NSInteger)row
*/
- (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
{
SPMySQLResult *theResult;
id tempValue;
NSMutableString *value = [NSMutableString string];
NSMutableString *argument = [NSMutableString string];
NSArray *columnNames;
NSUInteger i;
if ( row == -1 )
return @"";
// Retrieve the field names for this table from the data cache. This is used when requesting all data as part
// of the fieldListForQuery method, and also to decide whether or not to preserve the current filter/sort settings.
columnNames = [tableDataInstance columnNames];
NSArray *columnNames = [tableDataInstance columnNames];
// Get the primary key if there is one
if ( !keys ) {
setLimit = NO;
keys = [[NSMutableArray alloc] init];
theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [selectedTable backtickQuotedString]]];
SPMySQLResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [selectedTable backtickQuotedString]]];
if(!theResult) {
SPLog(@"no result from SHOW COLUMNS mysql query! Abort.");
return @"";
}
[theResult setReturnDataAsStrings:YES];
for (NSDictionary *eachRow in theResult) {
if ( [[eachRow objectForKey:@"Key"] isEqualToString:@"PRI"] ) {
@@ -3074,17 +3085,18 @@ - (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
#endif
}
NSMutableString *argument = [NSMutableString string];
// Walk through the keys list constructing the argument list
for ( i = 0 ; i < [keys count] ; i++ ) {
for (NSUInteger i = 0 ; i < [keys count] ; i++ ) {
if ( i )
[argument appendString:@" AND "];
id tempValue;
// Use the selected row if appropriate
if ( row >= 0 ) {
tempValue = [tableValues cellDataAtRow:row column:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"datacolumnindex"] integerValue]];
// Otherwise use the oldRow
}
// Otherwise use the oldRow
else {
tempValue = [oldRow objectAtIndex:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"datacolumnindex"] integerValue]];
}
@@ -3093,25 +3105,34 @@ - (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
[argument appendFormat:@"%@ IS NULL", [NSArrayObjectAtIndex(keys, i) backtickQuotedString]];
}
else if ([tempValue isSPNotLoaded]) {
NSLog(@"Exceptional case: SPNotLoaded object found for method “argumentForRow:”!");
SPLog(@"Exceptional case: SPNotLoaded object found! Abort.");
return @"";
}
else {
NSString *escVal;
NSString *fmt = @"%@";
// If the field is of type BIT then it needs a binary prefix
if ([[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"type"] isEqualToString:@"BIT"]) {
[value setString:[NSString stringWithFormat:@"b'%@'", [mySQLConnection escapeString:tempValue includingQuotes:NO]]];
escVal = [mySQLConnection escapeString:tempValue includingQuotes:NO];
fmt = @"b'%@'";
}
else if ([tempValue isKindOfClass:[SPMySQLGeometryData class]]) {
[value setString:[mySQLConnection escapeAndQuoteData:[tempValue data]]];
escVal = [mySQLConnection escapeAndQuoteData:[tempValue data]];
}
// BLOB/TEXT data
else if ([tempValue isKindOfClass:[NSData class]]) {
[value setString:[mySQLConnection escapeAndQuoteData:tempValue]];
escVal = [mySQLConnection escapeAndQuoteData:tempValue];
}
else
[value setString:[mySQLConnection escapeAndQuoteString:tempValue]];
[argument appendFormat:@"%@ = %@", [NSArrayObjectAtIndex(keys, i) backtickQuotedString], value];
else {
escVal = [mySQLConnection escapeAndQuoteString:tempValue];
}
if(!escVal) {
SPLog(@"(row=%ld) nil value for key <%@> is invalid! Abort.",row,NSArrayObjectAtIndex(keys, i));
return @"";
}
[argument appendFormat:@"%@ = %@", [NSArrayObjectAtIndex(keys, i) backtickQuotedString], [NSString stringWithFormat:fmt,escVal]];
}
}
@@ -239,7 +239,7 @@ - (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn
// issue that the table has no primary key
NSString *wherePart = [NSString stringWithString:[self argumentForRow:[tableContentView selectedRow]]];
if ([wherePart length] == 0) return NO;
if (![wherePart length]) return NO;
// If the selected cell hasn't been loaded, load it.
if ([[tableValues cellDataAtRow:rowIndex column:[[tableColumn identifier] integerValue]] isSPNotLoaded]) {

0 comments on commit 197b057

Please sign in to comment.