@@ -1884,12 +1884,13 @@ - (IBAction)duplicateRow:(id)sender
1884
1884
if ([prefs boolForKey:SPLoadBlobsAsNeeded]) {
1885
1885
1886
1886
// 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]) {
1888
1889
return;
1889
1890
}
1890
1891
1891
1892
// 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 ]];
1893
1894
dbDataRow = [queryResult getRowAsArray];
1894
1895
}
1895
1896
#endif
@@ -2203,9 +2204,14 @@ - (void)removeRowSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode c
2203
2204
while (anIndex != NSNotFound) {
2204
2205
2205
2206
// 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];
2209
2215
2210
2216
// Split deletion query into 64k chunks
2211
2217
if([deleteQuery length] > 64000) {
@@ -2825,7 +2831,15 @@ - (BOOL)saveRowToTable
2825
2831
[queryString appendFormat:@"%@ = %@",
2826
2832
[NSArrayObjectAtIndex(rowFieldsToSave, i) backtickQuotedString], NSArrayObjectAtIndex(rowValuesToSave, i)];
2827
2833
}
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];
2829
2843
}
2830
2844
2831
2845
[rowFieldsToSave release];
@@ -3029,25 +3043,22 @@ - (NSString *)argumentForRow:(NSInteger)row
3029
3043
*/
3030
3044
- (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
3031
3045
{
3032
- SPMySQLResult *theResult;
3033
- id tempValue;
3034
- NSMutableString *value = [NSMutableString string];
3035
- NSMutableString *argument = [NSMutableString string];
3036
- NSArray *columnNames;
3037
- NSUInteger i;
3038
-
3039
3046
if ( row == -1 )
3040
3047
return @"";
3041
3048
3042
3049
// Retrieve the field names for this table from the data cache. This is used when requesting all data as part
3043
3050
// 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];
3045
3052
3046
3053
// Get the primary key if there is one
3047
3054
if ( !keys ) {
3048
3055
setLimit = NO;
3049
3056
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
+ }
3051
3062
[theResult setReturnDataAsStrings:YES];
3052
3063
for (NSDictionary *eachRow in theResult) {
3053
3064
if ( [[eachRow objectForKey:@"Key"] isEqualToString:@"PRI"] ) {
@@ -3074,17 +3085,18 @@ - (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
3074
3085
#endif
3075
3086
}
3076
3087
3088
+ NSMutableString *argument = [NSMutableString string];
3077
3089
// 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++ ) {
3079
3091
if ( i )
3080
3092
[argument appendString:@" AND "];
3081
3093
3094
+ id tempValue;
3082
3095
// Use the selected row if appropriate
3083
3096
if ( row >= 0 ) {
3084
3097
tempValue = [tableValues cellDataAtRow:row column:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"datacolumnindex"] integerValue]];
3085
-
3086
- // Otherwise use the oldRow
3087
3098
}
3099
+ // Otherwise use the oldRow
3088
3100
else {
3089
3101
tempValue = [oldRow objectAtIndex:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(keys, i)] objectForKey:@"datacolumnindex"] integerValue]];
3090
3102
}
@@ -3093,25 +3105,34 @@ - (NSString *)argumentForRow:(NSInteger)row excludingLimits:(BOOL)excludeLimits
3093
3105
[argument appendFormat:@"%@ IS NULL", [NSArrayObjectAtIndex(keys, i) backtickQuotedString]];
3094
3106
}
3095
3107
else if ([tempValue isSPNotLoaded]) {
3096
- NSLog (@"Exceptional case: SPNotLoaded object found for method “argumentForRow:”! ");
3108
+ SPLog (@"Exceptional case: SPNotLoaded object found! Abort. ");
3097
3109
return @"";
3098
3110
}
3099
3111
else {
3112
+ NSString *escVal;
3113
+ NSString *fmt = @"%@";
3100
3114
// If the field is of type BIT then it needs a binary prefix
3101
3115
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'%@'";
3103
3118
}
3104
3119
else if ([tempValue isKindOfClass:[SPMySQLGeometryData class]]) {
3105
- [value setString: [mySQLConnection escapeAndQuoteData:[tempValue data] ]];
3120
+ escVal = [mySQLConnection escapeAndQuoteData:[tempValue data]];
3106
3121
}
3107
3122
// BLOB/TEXT data
3108
3123
else if ([tempValue isKindOfClass:[NSData class]]) {
3109
- [value setString: [mySQLConnection escapeAndQuoteData:tempValue] ];
3124
+ escVal = [mySQLConnection escapeAndQuoteData:tempValue];
3110
3125
}
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]];
3115
3136
}
3116
3137
}
3117
3138
0 commit comments