aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPTableContent.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/SPTableContent.m')
-rw-r--r--Source/SPTableContent.m152
1 files changed, 76 insertions, 76 deletions
diff --git a/Source/SPTableContent.m b/Source/SPTableContent.m
index 1e9bdf5f..82282b5d 100644
--- a/Source/SPTableContent.m
+++ b/Source/SPTableContent.m
@@ -2370,116 +2370,116 @@
/**
- * Tries to write a new row to the database.
- * Returns YES if row is written to database, otherwise NO; also returns YES if no row
- * is being edited and nothing has to be written to the database.
+ * Tries to write a new row to the table.
+ * Returns YES if row is written to table, otherwise NO; also returns YES if no row
+ * is being edited or nothing has to be written to the table.
*/
-- (BOOL)addRowToDB
+- (BOOL)saveRowToTable
{
- if([tablesListInstance tableType] == SPTableTypeView) return;
+ // Only handle tables - views should be handled per-cell.
+ if ([tablesListInstance tableType] == SPTableTypeView) return NO;
- NSMutableString *queryString;
- id rowObject;
- NSMutableString *rowValue = [NSMutableString string];
- NSString *currentTime = [[NSDate date] descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:nil];
- BOOL prefsLoadBlobsAsNeeded = [prefs boolForKey:SPLoadBlobsAsNeeded];
- NSInteger i;
-
- if ( !isEditingRow || currentlyEditingRow == -1) {
- return YES;
- }
-
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance];
+ // If no row is being edited, return success.
+ if (!isEditingRow) return YES;
- // If editing, compare the new row to the old row and if they are identical finish editing without saving.
+ // If editing, quickly compare the new row to the old row and if they are identical finish editing without saving.
if (!isEditingNewRow && [oldRow isEqualToArray:[tableValues rowContentsAtIndex:currentlyEditingRow]]) {
isEditingRow = NO;
currentlyEditingRow = -1;
- [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
return YES;
}
- NSMutableArray *fieldValues = [[NSMutableArray alloc] init];
-
- // Get the field values
- for ( i = 0 ; i < [dataColumns count] ; i++ ) {
+ // Iterate through the row contents, constructing the (ordered) arrays of keys and values to be saved
+ NSMutableArray *rowFieldsToSave = [[NSMutableArray alloc] initWithCapacity:[dataColumns count]];
+ NSMutableArray *rowValuesToSave = [[NSMutableArray alloc] initWithCapacity:[dataColumns count]];
+ NSInteger i;
+ id rowObject;
+ for (i = 0; i < [dataColumns count]; i++) {
rowObject = [tableValues cellDataAtRow:currentlyEditingRow column:i];
- // Add not loaded placeholders directly for easy comparison when added
- if (prefsLoadBlobsAsNeeded && !isEditingNewRow && [rowObject isSPNotLoaded])
- {
- [fieldValues addObject:[SPNotLoaded notLoaded]];
- continue;
-
- // Catch CURRENT_TIMESTAMP automatic updates - if the row is new and the cell value matches
- // the default value, or if the cell hasn't changed, update the current timestamp.
- } else if ([[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"onupdatetimestamp"] integerValue]
- && ( (isEditingNewRow && [rowObject isEqualTo:[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"default"]])
- || (!isEditingNewRow && [rowObject isEqualTo:NSArrayObjectAtIndex(oldRow, i)])))
- {
- [rowValue setString:@"CURRENT_TIMESTAMP"];
+ // Skip "not loaded" cells entirely - these only occur when editing tables when the
+ // preference setting is enabled, and don't need to be saved back to the table.
+ if ([rowObject isSPNotLoaded]) continue;
+
+ // If an edit has taken place, and the field value hasn't changed, the value
+ // can also be skipped
+ if (!isEditingNewRow && [rowObject isEqual:NSArrayObjectAtIndex(oldRow, i)]) continue;
- } else if ( [rowObject isNSNull]
- || ([rowObject isMemberOfClass:[NSString class]] && [[rowObject description] isEqualToString:@""]) ) {
+ // Prepare to derive the value to save
+ NSString *fieldValue;
+ NSString *fieldTypeGroup = [NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"typegrouping"];
- //NULL when user entered the nullValue string defined in the prefs or when a number field isn't set
- // problem: when a number isn't set, sequel-pro enters 0
- // -> second if argument isn't necessary!
- [rowValue setString:@"NULL"];
- } else if ( [[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"typegrouping"] isEqualToString:@"geometry"] ) {
- [rowValue setString:([rowObject isKindOfClass:[MCPGeometryData class]]) ? [[rowObject wktString] getGeomFromTextString] : [(NSString*)rowObject getGeomFromTextString]];
+ // Use NULL when the user has entered the nullValue string defined in the preferences,
+ // or when a numeric field is empty.
+ if ([rowObject isNSNull]
+ || (([fieldTypeGroup isEqualToString:@"float"] || [fieldTypeGroup isEqualToString:@"integer"])
+ && [[rowObject description] isEqualToString:@""]))
+ {
+ fieldValue = @"NULL";
+
+ // Convert geometry values to their string values
+ } else if ([fieldTypeGroup isEqualToString:@"geometry"]) {
+ fieldValue = ([rowObject isKindOfClass:[MCPGeometryData class]]) ? [[rowObject wktString] getGeomFromTextString] : [(NSString*)rowObject getGeomFromTextString];
+
// Convert the object to a string (here we can add special treatment for date-, number- and data-fields)
} else {
- // I don't believe any of these class matches are ever met at present.
- if ( [rowObject isKindOfClass:[NSCalendarDate class]] ) {
- [rowValue setString:[NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[rowObject description]]]];
- } else if ( [rowObject isKindOfClass:[NSNumber class]] ) {
- [rowValue setString:[rowObject stringValue]];
- } else if ( [rowObject isKindOfClass:[NSData class]] ) {
- [rowValue setString:[NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:rowObject]]];
+ // I believe these class matches are not ever met at present.
+ if ([rowObject isKindOfClass:[NSCalendarDate class]]) {
+ fieldValue = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[rowObject description]]];
+ } else if ([rowObject isKindOfClass:[NSNumber class]]) {
+ fieldValue = [rowObject stringValue];
+
+ // Convert data to its hex representation
+ } else if ([rowObject isKindOfClass:[NSData class]]) {
+ fieldValue = [NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:rowObject]];
+
} else {
if ([[rowObject description] isEqualToString:@"CURRENT_TIMESTAMP"]) {
- [rowValue setString:@"CURRENT_TIMESTAMP"];
- } else if ([[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"typegrouping"] isEqualToString:@"bit"]) {
- [rowValue setString:[NSString stringWithFormat:@"b'%@'", ((![[rowObject description] length] || [[rowObject description] isEqualToString:@"0"]) ? @"0" : [rowObject description])]];
- } else if ([[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"typegrouping"] isEqualToString:@"date"]
- && [[rowObject description] isEqualToString:@"NOW()"]) {
- [rowValue setString:@"NOW()"];
+ fieldValue = @"CURRENT_TIMESTAMP";
+ } else if ([fieldTypeGroup isEqualToString:@"bit"]) {
+ fieldValue = [NSString stringWithFormat:@"b'%@'", ((![[rowObject description] length] || [[rowObject description] isEqualToString:@"0"]) ? @"0" : [rowObject description])];
+ } else if ([fieldTypeGroup isEqualToString:@"date"] && [[rowObject description] isEqualToString:@"NOW()"]) {
+ fieldValue = @"NOW()";
} else {
- [rowValue setString:[NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[rowObject description]]]];
+ fieldValue = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[rowObject description]]];
}
}
}
- [fieldValues addObject:[NSString stringWithString:rowValue]];
+
+ // Store the key and value in the ordered arrays for saving.
+ [rowFieldsToSave addObject:[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"name"]];
+ [rowValuesToSave addObject:fieldValue];
}
- // Use INSERT syntax when creating new rows - no need to do not loaded checking, as all values have been entered
- if ( isEditingNewRow ) {
+ [[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance];
+ NSMutableString *queryString;
+
+ // Use INSERT syntax when creating new rows
+ if (isEditingNewRow) {
queryString = [NSString stringWithFormat:@"INSERT INTO %@ (%@) VALUES (%@)",
- [selectedTable backtickQuotedString], [[tableDataInstance columnNames] componentsJoinedAndBacktickQuoted], [fieldValues componentsJoinedByString:@","]];
- // Use UPDATE syntax otherwise
+ [selectedTable backtickQuotedString], [rowFieldsToSave componentsJoinedAndBacktickQuoted], [rowValuesToSave componentsJoinedByString:@", "]];
+
+ // Otherwise use an UPDATE syntax to save only the changed cells - if this point is reached,
+ // the equality test has failed and so there is always at least one changed cell
} else {
- BOOL firstCellOutput = NO;
queryString = [NSMutableString stringWithFormat:@"UPDATE %@ SET ", [selectedTable backtickQuotedString]];
- for ( i = 0 ; i < [dataColumns count] ; i++ ) {
-
- // If data column loading is deferred and the value is the not loaded string, skip this cell
- if (prefsLoadBlobsAsNeeded && [[fieldValues objectAtIndex:i] isSPNotLoaded]) continue;
-
- if (firstCellOutput) [queryString appendString:@", "];
- else firstCellOutput = YES;
-
+ for (i = 0; i < [rowFieldsToSave count]; i++) {
+ if (i) [queryString appendString:@", "];
[queryString appendFormat:@"%@ = %@",
- [[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"name"] backtickQuotedString], [fieldValues objectAtIndex:i]];
+ [NSArrayObjectAtIndex(rowFieldsToSave, i) backtickQuotedString],
+ NSArrayObjectAtIndex(rowValuesToSave, i)];
}
[queryString appendFormat:@" WHERE %@", [self argumentForRow:-2]];
}
+ [rowFieldsToSave release];
+ [rowValuesToSave release];
+
+ // Run the query
[mySQLConnection queryString:queryString];
- [fieldValues release];
[[NSNotificationCenter defaultCenter] postNotificationOnMainThreadWithName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance];
// If no rows have been changed, show error if appropriate.
@@ -2494,7 +2494,7 @@
isEditingRow = NO;
isEditingNewRow = NO;
currentlyEditingRow = -1;
- [[SPQueryController sharedQueryController] showErrorInConsole:[NSString stringWithFormat:NSLocalizedString(@"/* WARNING %@ No rows have been affected */\n", @"warning shown in the console when no rows have been affected after writing to the db"), currentTime] connection:[tableDocumentInstance name]];
+ [[SPQueryController sharedQueryController] showErrorInConsole:NSLocalizedString(@"/* WARNING: No rows have been affected */\n", @"warning shown in the console when no rows have been affected after writing to the db") connection:[tableDocumentInstance name]];
return YES;
// On success...
@@ -2582,7 +2582,7 @@
isSavingRow = YES;
// Attempt to save the row, and return YES if the save succeeded.
- if ([self addRowToDB]) {
+ if ([self saveRowToTable]) {
isSavingRow = NO;
return YES;
}