Skip to content

Commit 197b057

Browse files
committed
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)
1 parent f6be61c commit 197b057

File tree

3 files changed

+51
-29
lines changed

3 files changed

+51
-29
lines changed

Source/SPCopyTable.m

+3-2
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,9 @@ - (NSString *)rowsAsSqlInsertsOnlySelectedRows:(BOOL)onlySelected
495495
// If the data is not loaded, attempt to fetch the value
496496
if ([cellData isSPNotLoaded] && [[self delegate] isKindOfClass:spTableContentClass]) {
497497

498+
NSString *whereArgument = [tableInstance argumentForRow:rowIndex];
498499
// Abort if no table name given, not table content, or if there are no indices on this table
499-
if (!selectedTable || ![[self delegate] isKindOfClass:spTableContentClass] || ![(NSString*)[tableInstance argumentForRow:rowIndex] length]) {
500+
if (!selectedTable || ![[self delegate] isKindOfClass:spTableContentClass] || ![whereArgument length]) {
500501
NSBeep();
501502
free(columnMappings);
502503
free(columnTypes);
@@ -509,7 +510,7 @@ - (NSString *)rowsAsSqlInsertsOnlySelectedRows:(BOOL)onlySelected
509510
[NSString stringWithFormat:@"SELECT %@ FROM %@ WHERE %@",
510511
[NSArrayObjectAtIndex(tbHeader, columnMappings[c]) backtickQuotedString],
511512
[selectedTable backtickQuotedString],
512-
[tableInstance argumentForRow:rowIndex]]];
513+
whereArgument]];
513514
}
514515

515516
// Check for NULL value

Source/SPTableContent.m

+47-26
Original file line numberDiff line numberDiff line change
@@ -1884,12 +1884,13 @@ - (IBAction)duplicateRow:(id)sender
18841884
if ([prefs boolForKey:SPLoadBlobsAsNeeded]) {
18851885

18861886
// Abort if there are no indices on this table - argumentForRow will display an error.
1887-
if (![[self argumentForRow:[tableContentView selectedRow]] length]) {
1887+
NSString *whereArgument = [self argumentForRow:[tableContentView selectedRow]];
1888+
if (![whereArgument length]) {
18881889
return;
18891890
}
18901891

18911892
// If we have indexes, use argumentForRow
1892-
queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", [selectedTable backtickQuotedString], [self argumentForRow:[tableContentView selectedRow]]]];
1893+
queryResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT * FROM %@ WHERE %@", [selectedTable backtickQuotedString], whereArgument]];
18931894
dbDataRow = [queryResult getRowAsArray];
18941895
}
18951896
#endif
@@ -2203,9 +2204,14 @@ - (void)removeRowSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode c
22032204
while (anIndex != NSNotFound) {
22042205

22052206
// Build the AND clause of PRIMARY KEYS
2206-
[deleteQuery appendString:@"("];
2207-
[deleteQuery appendString:[self argumentForRow:anIndex excludingLimits:YES]];
2208-
[deleteQuery appendString:@")"];
2207+
NSString *whereArg = [self argumentForRow:anIndex excludingLimits:YES];
2208+
if(![whereArg length]) {
2209+
SPLog(@"empty WHERE clause not acceptable for DELETE! Abort.");
2210+
NSBeep();
2211+
return;
2212+
}
2213+
2214+
[deleteQuery appendFormat:@"(%@)",whereArg];
22092215

22102216
// Split deletion query into 64k chunks
22112217
if([deleteQuery length] > 64000) {
@@ -2825,7 +2831,15 @@ - (BOOL)saveRowToTable
28252831
[queryString appendFormat:@"%@ = %@",
28262832
[NSArrayObjectAtIndex(rowFieldsToSave, i) backtickQuotedString], NSArrayObjectAtIndex(rowValuesToSave, i)];
28272833
}
2828-
[queryString appendFormat:@" WHERE %@", [self argumentForRow:-2]];
2834+
NSString *whereArg = [self argumentForRow:-2];
2835+
if(![whereArg length]) {
2836+
SPLog(@"Did not find plausible WHERE condition for UPDATE.");
2837+
NSBeep();
2838+
[rowFieldsToSave release];
2839+
[rowValuesToSave release];
2840+
return NO;
2841+
}
2842+
[queryString appendFormat:@" WHERE %@", whereArg];
28292843
}
28302844

28312845
[rowFieldsToSave release];
@@ -3029,25 +3043,22 @@ - (NSString *)argumentForRow:(NSInteger)row
30293043
*/
30303044
- (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
30313045
{
3032-
SPMySQLResult *theResult;
3033-
id tempValue;
3034-
NSMutableString *value = [NSMutableString string];
3035-
NSMutableString *argument = [NSMutableString string];
3036-
NSArray *columnNames;
3037-
NSUInteger i;
3038-
30393046
if ( row == -1 )
30403047
return @"";
30413048

30423049
// Retrieve the field names for this table from the data cache. This is used when requesting all data as part
30433050
// of the fieldListForQuery method, and also to decide whether or not to preserve the current filter/sort settings.
3044-
columnNames = [tableDataInstance columnNames];
3051+
NSArray *columnNames = [tableDataInstance columnNames];
30453052

30463053
// Get the primary key if there is one
30473054
if ( !keys ) {
30483055
setLimit = NO;
30493056
keys = [[NSMutableArray alloc] init];
3050-
theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [selectedTable backtickQuotedString]]];
3057+
SPMySQLResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@", [selectedTable backtickQuotedString]]];
3058+
if(!theResult) {
3059+
SPLog(@"no result from SHOW COLUMNS mysql query! Abort.");
3060+
return @"";
3061+
}
30513062
[theResult setReturnDataAsStrings:YES];
30523063
for (NSDictionary *eachRow in theResult) {
30533064
if ( [[eachRow objectForKey:@"Key"] isEqualToString:@"PRI"] ) {
@@ -3074,17 +3085,18 @@ - (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
30743085
#endif
30753086
}
30763087

3088+
NSMutableString *argument = [NSMutableString string];
30773089
// Walk through the keys list constructing the argument list
3078-
for ( i = 0 ; i < [keys count] ; i++ ) {
3090+
for (NSUInteger i = 0 ; i < [keys count] ; i++ ) {
30793091
if ( i )
30803092
[argument appendString:@" AND "];
30813093

3094+
id tempValue;
30823095
// Use the selected row if appropriate
30833096
if ( row >= 0 ) {
30843097
tempValue = [tableValues cellDataAtRow:row column:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"datacolumnindex"] integerValue]];
3085-
3086-
// Otherwise use the oldRow
30873098
}
3099+
// Otherwise use the oldRow
30883100
else {
30893101
tempValue = [oldRow objectAtIndex:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"datacolumnindex"] integerValue]];
30903102
}
@@ -3093,25 +3105,34 @@ - (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
30933105
[argument appendFormat:@"%@ IS NULL", [NSArrayObjectAtIndex(keys, i) backtickQuotedString]];
30943106
}
30953107
else if ([tempValue isSPNotLoaded]) {
3096-
NSLog(@"Exceptional case: SPNotLoaded object found for method “argumentForRow:”!");
3108+
SPLog(@"Exceptional case: SPNotLoaded object found! Abort.");
30973109
return @"";
30983110
}
30993111
else {
3112+
NSString *escVal;
3113+
NSString *fmt = @"%@";
31003114
// If the field is of type BIT then it needs a binary prefix
31013115
if ([[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"type"] isEqualToString:@"BIT"]) {
3102-
[value setString:[NSString stringWithFormat:@"b'%@'", [mySQLConnection escapeString:tempValue includingQuotes:NO]]];
3116+
escVal = [mySQLConnection escapeString:tempValue includingQuotes:NO];
3117+
fmt = @"b'%@'";
31033118
}
31043119
else if ([tempValue isKindOfClass:[SPMySQLGeometryData class]]) {
3105-
[value setString:[mySQLConnection escapeAndQuoteData:[tempValue data]]];
3120+
escVal = [mySQLConnection escapeAndQuoteData:[tempValue data]];
31063121
}
31073122
// BLOB/TEXT data
31083123
else if ([tempValue isKindOfClass:[NSData class]]) {
3109-
[value setString:[mySQLConnection escapeAndQuoteData:tempValue]];
3124+
escVal = [mySQLConnection escapeAndQuoteData:tempValue];
31103125
}
3111-
else
3112-
[value setString:[mySQLConnection escapeAndQuoteString:tempValue]];
3113-
3114-
[argument appendFormat:@"%@ = %@", [NSArrayObjectAtIndex(keys, i) backtickQuotedString], value];
3126+
else {
3127+
escVal = [mySQLConnection escapeAndQuoteString:tempValue];
3128+
}
3129+
3130+
if(!escVal) {
3131+
SPLog(@"(row=%ld) nil value for key <%@> is invalid! Abort.",row,NSArrayObjectAtIndex(keys, i));
3132+
return @"";
3133+
}
3134+
3135+
[argument appendFormat:@"%@ = %@", [NSArrayObjectAtIndex(keys, i) backtickQuotedString], [NSString stringWithFormat:fmt,escVal]];
31153136
}
31163137
}
31173138

Source/SPTableContentDelegate.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ - (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn
239239
// issue that the table has no primary key
240240
NSString *wherePart = [NSString stringWithString:[self argumentForRow:[tableContentView selectedRow]]];
241241

242-
if ([wherePart length] == 0) return NO;
242+
if (![wherePart length]) return NO;
243243

244244
// If the selected cell hasn't been loaded, load it.
245245
if ([[tableValues cellDataAtRow:rowIndex column:[[tableColumn identifier] integerValue]] isSPNotLoaded]) {

0 commit comments

Comments
 (0)