diff options
author | rowanbeentje <rowan@beent.je> | 2009-11-28 19:58:03 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2009-11-28 19:58:03 +0000 |
commit | 657966e2c2b37a988b145813e1787af4e6a962ad (patch) | |
tree | 579d83d09178e7fd266e803d6deadf2dbb1bb9ba /Source/CustomQuery.m | |
parent | 19867175eed5aebee585c1ba6d8901176422703d (diff) | |
download | sequelpro-657966e2c2b37a988b145813e1787af4e6a962ad.tar.gz sequelpro-657966e2c2b37a988b145813e1787af4e6a962ad.tar.bz2 sequelpro-657966e2c2b37a988b145813e1787af4e6a962ad.zip |
- When working with the storage arrays for CustomQuery and TableContent, use thread locking to ensure data safety while the table is loading. This should fix intermittent loading and reload issues, including part of #463 and should address Issue #482
Diffstat (limited to 'Source/CustomQuery.m')
-rw-r--r-- | Source/CustomQuery.m | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/Source/CustomQuery.m b/Source/CustomQuery.m index 826258cd..522fb5d0 100644 --- a/Source/CustomQuery.m +++ b/Source/CustomQuery.m @@ -807,7 +807,9 @@ // Remove all items from the table fullResultCount = 0; [customQueryView performSelectorOnMainThread:@selector(noteNumberOfRowsChanged) withObject:nil waitUntilDone:YES]; + pthread_mutex_lock(&fullResultLock); [fullResult removeAllObjects]; + pthread_mutex_unlock(&fullResultLock); // Set up an autorelease pool for row processing dataLoadingPool = [[NSAutoreleasePool alloc] init]; @@ -815,8 +817,10 @@ // Loop through the result rows as they become available while (tempRow = [theResult fetchNextRowAsArray]) { + pthread_mutex_lock(&fullResultLock); NSMutableArrayAddObject(fullResult, [NSMutableArray arrayWithArray:tempRow]); fullResultCount++; + pthread_mutex_unlock(&fullResultLock); // Update the count of rows processed rowsProcessed++; @@ -1344,16 +1348,34 @@ - (void)tableView:(CMCopyTable *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)aTableColumn row:(NSInteger)rowIndex { if (aTableView == customQueryView) { - - // Perform various result set checks to prevent crashes - if ((fullResultCount == 0) || (rowIndex > fullResultCount)) return; - + // For NULL cell's display the user's NULL value placeholder in grey to easily distinguish it from other values if ([cell respondsToSelector:@selector(setTextColor:)]) { - - id value = NSArrayObjectAtIndex(NSArrayObjectAtIndex(fullResult, rowIndex), [[aTableColumn identifier] intValue]); + NSUInteger columnIndex = [[aTableColumn identifier] intValue]; + id theValue = nil; + + // While the table is being loaded, additional validation is required - data + // locks must be used to avoid crashes, and indexes higher than the available + // rows or columns may be requested. Use gray to show loading in these cases. + if (isWorking) { + pthread_mutex_lock(&fullResultLock); + if (rowIndex < fullResultCount) { + NSMutableArray *rowData = NSArrayObjectAtIndex(fullResult, rowIndex); + if (columnIndex < [rowData count]) { + theValue = NSArrayObjectAtIndex(rowData, columnIndex); + } + } + pthread_mutex_unlock(&fullResultLock); + + if (!theValue) { + [cell setTextColor:[NSColor lightGrayColor]]; + return; + } + } else { + theValue = NSArrayObjectAtIndex(NSArrayObjectAtIndex(fullResult, rowIndex), columnIndex); + } - [cell setTextColor:[value isNSNull] ? [NSColor lightGrayColor] : [NSColor blackColor]]; + [cell setTextColor:[theValue isNSNull] ? [NSColor lightGrayColor] : [NSColor blackColor]]; } } } @@ -1364,19 +1386,35 @@ - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { if (aTableView == customQueryView) { + NSUInteger columnIndex = [[aTableColumn identifier] intValue]; + id theValue = nil; + + // While the table is being loaded, additional validation is required - data + // locks must be used to avoid crashes, and indexes higher than the available + // rows or columns may be requested. Return "..." to indicate loading in these + // cases. + if (isWorking) { + pthread_mutex_lock(&fullResultLock); + if (rowIndex < fullResultCount) { + NSMutableArray *rowData = NSArrayObjectAtIndex(fullResult, rowIndex); + if (columnIndex < [rowData count]) { + theValue = NSArrayObjectAtIndex(rowData, columnIndex); + } + } + pthread_mutex_unlock(&fullResultLock); + + if (!theValue) return @"..."; + } else { + theValue = NSArrayObjectAtIndex(NSArrayObjectAtIndex(fullResult, rowIndex), columnIndex); + } - // Perform various result set checks to prevent crashes - if ((fullResultCount == 0) || (rowIndex > fullResultCount)) return nil; - - id value = NSArrayObjectAtIndex(NSArrayObjectAtIndex(fullResult, rowIndex), [[aTableColumn identifier] intValue]); - - if ([value isKindOfClass:[NSData class]]) - return [value shortStringRepresentationUsingEncoding:[mySQLConnection encoding]]; + if ([theValue isKindOfClass:[NSData class]]) + return [theValue shortStringRepresentationUsingEncoding:[mySQLConnection encoding]]; - if ([value isNSNull]) + if ([theValue isNSNull]) return [prefs objectForKey:SPNullValue]; - return value; + return theValue; } else { return @""; @@ -2607,6 +2645,7 @@ */ - (void) startDocumentTaskForTab:(NSNotification *)aNotification { + isWorking = YES; // Only proceed if this view is selected. if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:MAIN_TOOLBAR_CUSTOM_QUERY]) @@ -2623,6 +2662,7 @@ */ - (void) endDocumentTaskForTab:(NSNotification *)aNotification { + isWorking = NO; // Only proceed if this view is selected. if (![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:MAIN_TOOLBAR_CUSTOM_QUERY]) |