aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2009-10-16 16:46:41 +0000
committerBibiko <bibiko@eva.mpg.de>2009-10-16 16:46:41 +0000
commit967579ef1225a134c50a686ee7caa9a3b5e293f3 (patch)
tree11470982216c5f9579c26bfa07815b73a081e0f5
parent507d0089c6bb73a01129f1e356d1e88ca53afb55 (diff)
downloadsequelpro-967579ef1225a134c50a686ee7caa9a3b5e293f3.tar.gz
sequelpro-967579ef1225a134c50a686ee7caa9a3b5e293f3.tar.bz2
sequelpro-967579ef1225a134c50a686ee7caa9a3b5e293f3.zip
• fixed SPArrayAdditions method 'componentsJoinedByCommas' to use a mutable string to avoid crashes if array has a very large number of items (malloc error due to reassigning a NSString pointer)
• added to SPTableData method - (NSArray *) primaryKeyColumnNames - returns all column names which are set as PRIMARY KEYs - return nil if no PRIMARY KEY is set • improved the deletion of rows - if current table has only one PRIMARY KEY field delete all rows via DELETE FROM table WHERE pri_key IN (…) whereby the deletion query will be splitted into 256k chunks Note: line 1790ff It has to be implemented a workaround for tables with more than one PRIMARY KEY – maybe via DELETE FROM table WHERE ( (pri_key1='…' AND pri_key2='…') OR (… AND …) OR … ) splitted in 256k chunks as well
-rw-r--r--Source/SPArrayAdditions.m10
-rw-r--r--Source/SPTableData.h2
-rw-r--r--Source/SPTableData.m38
-rw-r--r--Source/TableContent.m83
4 files changed, 111 insertions, 22 deletions
diff --git a/Source/SPArrayAdditions.m b/Source/SPArrayAdditions.m
index e19869fa..bbc732af 100644
--- a/Source/SPArrayAdditions.m
+++ b/Source/SPArrayAdditions.m
@@ -44,15 +44,15 @@
- (NSString *)componentsJoinedByCommas
{
- NSString *result = [NSString string];
+ NSMutableString *result = [NSMutableString string];
+ [result setString:@""];
+
for (NSString *component in self)
{
if ([result length])
- {
- result = [result stringByAppendingString:@","];
- }
+ [result appendString:@","];
- result = [result stringByAppendingString:component];
+ [result appendString:component];
}
return result;
}
diff --git a/Source/SPTableData.h b/Source/SPTableData.h
index 4df13719..928d2b54 100644
--- a/Source/SPTableData.h
+++ b/Source/SPTableData.h
@@ -62,5 +62,7 @@
- (NSDictionary *) informationForView:(NSString *)viewName;
- (BOOL) updateStatusInformationForCurrentTable;
- (NSDictionary *) parseFieldDefinitionStringParts:(NSArray *)definitionParts;
+- (NSArray *) primaryKeyColumnNames;
+
@end
diff --git a/Source/SPTableData.m b/Source/SPTableData.m
index ec02c301..52911330 100644
--- a/Source/SPTableData.m
+++ b/Source/SPTableData.m
@@ -968,6 +968,44 @@
return [fieldDetails autorelease];
}
+/*
+ * Return the column names which are set to PRIMIARY KEY; returns nil if no PRIMARY KEY is set.
+ */
+- (NSArray *)primaryKeyColumnNames
+{
+
+ NSString *selectedTable = [tableListInstance tableName];
+ if(![selectedTable length]) return nil;
+
+ MCPResult *r;
+ NSArray *resultRow;
+ NSInteger i;
+ NSMutableArray *keyColumns = [NSMutableArray array];
+
+ r = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@ WHERE `key` = 'PRI'", [selectedTable backtickQuotedString]]];
+
+ if([r numOfRows] < 1) return nil;
+
+ if (![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) {
+ if ([mySQLConnection isConnected])
+ NSRunAlertPanel(@"Error", [NSString stringWithFormat:@"An error occured while retrieving the PRIAMRY KEY data:\n\n%@", [mySQLConnection getLastErrorMessage]], @"OK", nil, nil);
+ return nil;
+ }
+
+
+ for( i = 0; i < [r numOfRows]; i++ ) {
+ resultRow = [r fetchRowAsArray];
+ [keyColumns addObject:[NSArrayObjectAtIndex(resultRow, 0) description]];
+ }
+
+ if([keyColumns count])
+ return keyColumns;
+
+ return nil;
+}
+
+#pragma mark -
+
- (void) dealloc
{
[columns release];
diff --git a/Source/TableContent.m b/Source/TableContent.m
index 12658d30..49f8e27c 100644
--- a/Source/TableContent.m
+++ b/Source/TableContent.m
@@ -1655,7 +1655,8 @@
if ( [tempValue isNSNull] ) {
[argument appendString:[NSString stringWithFormat:@"%@ IS NULL", [NSArrayObjectAtIndex(keys, i) backtickQuotedString]]];
} else if ( [tempValue isSPNotLoaded] ) {
- // TODO
+ NSLog(@"Exceptional case: SPNotLoaded object found for method “argumentForRow:”!");
+ return @"";
} else {
if ( [tempValue isKindOfClass:[NSData class]] )
@@ -1784,30 +1785,78 @@
NSUInteger index = [selectedRows firstIndex];
- while (index != NSNotFound) {
+ NSArray *primaryKeyFieldNames = [tableDataInstance primaryKeyColumnNames];
+
+ // TODO tentative → || [primaryKeyFields count] != 1
+ if(primaryKeyFieldNames == nil || [primaryKeyFieldNames count] != 1) {
+ // delete row by row
+ while (index != NSNotFound) {
- wherePart = [NSString stringWithString:[self argumentForRow:index]];
+ wherePart = [NSString stringWithString:[self argumentForRow:index]];
- //argumentForRow might return empty query, in which case we shouldn't execute the partial query
- if([wherePart length]) {
- [mySQLConnection queryString:[NSString stringWithFormat:@"DELETE FROM %@ WHERE %@", [selectedTable backtickQuotedString], wherePart]];
+ //argumentForRow might return empty query, in which case we shouldn't execute the partial query
+ if([wherePart length]) {
+ [mySQLConnection queryString:[NSString stringWithFormat:@"DELETE FROM %@ WHERE %@", [selectedTable backtickQuotedString], wherePart]];
- // Check for errors
- if ( ![mySQLConnection affectedRows] || ![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) {
- // If error delete that index from selectedRows for reloading table if
- // "ReloadAfterRemovingRow" is disbaled
+ // Check for errors
+ if ( ![mySQLConnection affectedRows] || ![[mySQLConnection getLastErrorMessage] isEqualToString:@""]) {
+ // If error delete that index from selectedRows for reloading table if
+ // "ReloadAfterRemovingRow" is disbaled
+ if(!reloadAfterRemovingRow)
+ [selectedRows removeIndex:index];
+ errors++;
+ }
+ } else {
if(!reloadAfterRemovingRow)
[selectedRows removeIndex:index];
errors++;
}
- } else {
- if(!reloadAfterRemovingRow)
- [selectedRows removeIndex:index];
- errors++;
+ index = [selectedRows indexGreaterThanIndex:index];
}
- index = [selectedRows indexGreaterThanIndex:index];
- }
+ } else {
+ // if table has only one PRIMARY KEY
+ // delete the fast way by using the PRIMARY KEY in an IN clause
+ NSMutableString *deleteQuery = [NSMutableString string];
+ NSInteger affectedRows = 0;
+
+ [deleteQuery setString:[NSString stringWithFormat:@"DELETE FROM %@ WHERE %@ IN (", [selectedTable backtickQuotedString], [NSArrayObjectAtIndex(primaryKeyFieldNames,0) backtickQuotedString]]];
+
+ while (index != NSNotFound) {
+
+ id keyValue = [NSArrayObjectAtIndex(tableValues, index) objectAtIndex:[[[tableDataInstance columnWithName:NSArrayObjectAtIndex(primaryKeyFieldNames,0)] objectForKey:@"datacolumnindex"] intValue]];
+
+ if([keyValue isKindOfClass:[NSData class]])
+ [deleteQuery appendString:[NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:keyValue]]];
+ else
+ [deleteQuery appendString:[NSString stringWithFormat:@"'%@'", [keyValue description]]];
+
+ // Split deletion query into 256k chunks
+ if([deleteQuery length] > 256000) {
+ [deleteQuery appendString:@")"];
+ [mySQLConnection queryString:deleteQuery];
+ // Remember affected rows for error checking
+ affectedRows += [mySQLConnection affectedRows];
+ // Reinit a new deletion query
+ [deleteQuery setString:[NSString stringWithFormat:@"DELETE FROM %@ WHERE %@ IN (", [selectedTable backtickQuotedString], [NSArrayObjectAtIndex(primaryKeyFieldNames,0) backtickQuotedString]]];
+ } else {
+ [deleteQuery appendString:@","];
+ }
+ index = [selectedRows indexGreaterThanIndex:index];
+ }
+
+ // Check if deleteQuery's maximal length was reached for the last index
+ // if yes omit the empty query
+ if(![deleteQuery hasSuffix:@"("]) {
+ // Replace final , by ) and delete the remaining rows
+ [deleteQuery setString:[NSString stringWithFormat:@"%@)", [deleteQuery substringToIndex:([deleteQuery length]-1)]]];
+ [mySQLConnection queryString:deleteQuery];
+ // Remember affected rows for error checking
+ affectedRows += [mySQLConnection affectedRows];
+ }
+ errors = [selectedRows count] - affectedRows;
+ }
+
// Restore Console Log window's updating bahaviour
[[SPQueryController sharedQueryController] setAllowConsoleUpdate:consoleUpdateStatus];
@@ -2327,7 +2376,7 @@
}
BOOL isBlob = [tableDataInstance columnIsBlobOrText:[[aTableColumn headerCell] stringValue]];
-
+
// Open the sheet if the multipleLineEditingButton is enabled or the column was a blob or a text.
if ([multipleLineEditingButton state] == NSOnState || isBlob) {