aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/SPCustomQuery.h2
-rw-r--r--Source/SPCustomQuery.m52
-rw-r--r--Source/SPDataStorage.h7
-rw-r--r--Source/SPDataStorage.m12
4 files changed, 38 insertions, 35 deletions
diff --git a/Source/SPCustomQuery.h b/Source/SPCustomQuery.h
index e976f716..fe31be6d 100644
--- a/Source/SPCustomQuery.h
+++ b/Source/SPCustomQuery.h
@@ -160,8 +160,6 @@
SPDataStorage *resultData;
pthread_mutex_t resultDataLock;
- NSCondition *resultLoadingCondition;
- NSInteger resultDataCount;
NSArray *cqColumnDefinition;
NSString *lastExecutedQuery;
NSInteger editedRow;
diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m
index 591bcb12..3cbd6a4d 100644
--- a/Source/SPCustomQuery.m
+++ b/Source/SPCustomQuery.m
@@ -61,6 +61,7 @@
#import "SPAppController.h"
#import "SPBundleHTMLOutputController.h"
#endif
+#import "SPFunctions.h"
#import <pthread.h>
#import <SPMySQL/SPMySQL.h>
@@ -884,7 +885,7 @@
(long)totalAffectedRows
];
}
- if(resultDataCount) {
+ if([resultData count]) {
// we were running a query that returns a result set (ie. SELECT).
// TODO: mysql_query() returns as soon as the first result row is found (which might be pretty soon when using indexes / not doing aggregations)
// and that makes our query time measurement pretty useless (see #264)
@@ -905,7 +906,7 @@
#endif
// If no results were returned, redraw the empty table and post notifications before returning.
- if ( !resultDataCount ) {
+ if ( ![resultData count] ) {
[customQueryView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
// Notify any listeners that the query has completed
@@ -931,8 +932,6 @@
return;
}
- [[customQueryView onMainThread] reloadData];
-
// Restore the result view origin if appropriate
if (!NSEqualRects(selectionViewportToRestore, NSZeroRect)) {
@@ -976,12 +975,12 @@
*/
- (void)updateResultStore:(SPMySQLStreamingResultStore *)theResultStore
{
-
- // Remove all items from the table
- resultDataCount = 0;
- [customQueryView performSelectorOnMainThread:@selector(noteNumberOfRowsChanged) withObject:nil waitUntilDone:YES];
pthread_mutex_lock(&resultDataLock);
- [resultData removeAllRows];
+ // Remove all items from the table
+ SPMainQSync(^{
+ [resultData removeAllRows];
+ [customQueryView noteNumberOfRowsChanged];
+ });
// Add the new store
[resultData setDataStorage:theResultStore updatingExisting:NO];
@@ -993,16 +992,9 @@
// Set up the table updates timer and wait for it to notify this thread about completion
[[self onMainThread] initQueryLoadTimer];
- [resultLoadingCondition lock];
- while (![resultData dataDownloaded]) {
- [resultLoadingCondition waitUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
- }
- [resultLoadingCondition unlock];
-
- // If the final column autoresize wasn't performed, perform it
- if (queryLoadLastRowCount < 200) [[self onMainThread] autosizeColumns];
-
- [customQueryView performSelectorOnMainThread:@selector(noteNumberOfRowsChanged) withObject:nil waitUntilDone:NO];
+ [resultData awaitDataDownloaded];
+
+ // Any further UI updates are the responsibility of the timer callback
}
/**
@@ -1492,23 +1484,20 @@
*/
- (void) queryLoadUpdate:(NSTimer *)theTimer
{
- resultDataCount = [resultData count];
-
+ NSUInteger resultDataCount = [resultData count];
+
if (queryLoadTimerTicksSinceLastUpdate < queryLoadInterfaceUpdateInterval) {
queryLoadTimerTicksSinceLastUpdate++;
return;
}
if ([resultData dataDownloaded]) {
- [resultLoadingCondition lock];
- [resultLoadingCondition signal];
[self clearQueryLoadTimer];
- [resultLoadingCondition unlock];
}
// Check whether a table update is required, based on whether new rows are
// available to display.
- if (resultDataCount == (NSInteger)queryLoadLastRowCount) {
+ if (resultDataCount == queryLoadLastRowCount) {
return;
}
@@ -1555,7 +1544,7 @@
*/
- (NSUInteger)currentResultRowCount
{
- return resultDataCount;
+ return [resultData count];
}
/**
@@ -2084,7 +2073,7 @@
*/
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
- return (aTableView == customQueryView) ? (resultData == nil) ? 0 : resultDataCount : 0;
+ return (aTableView == customQueryView) ? (resultData == nil) ? 0 : [resultData count] : 0;
}
/**
@@ -2109,7 +2098,7 @@
if (isWorking) {
pthread_mutex_lock(&resultDataLock);
- if (rowIndex < resultDataCount && columnIndex < [resultData columnCount]) {
+ if (SPIntS2U(rowIndex) < [resultData count] && columnIndex < [resultData columnCount]) {
showCellAsGray = [resultData cellIsNullOrUnloadedAtRow:rowIndex column:columnIndex];
} else {
showCellAsGray = YES;
@@ -2410,7 +2399,7 @@
// cases.
if (isWorking) {
pthread_mutex_lock(&resultDataLock);
- if (row < resultDataCount && (NSUInteger)[[aTableColumn identifier] integerValue] < [resultData columnCount]) {
+ if (SPIntS2U(row) < [resultData count] && (NSUInteger)[[aTableColumn identifier] integerValue] < [resultData columnCount]) {
theValue = [[SPDataStorageObjectAtRowAndColumn(resultData, row, [[aTableColumn identifier] integerValue]) copy] autorelease];
}
pthread_mutex_unlock(&resultDataLock);
@@ -3776,7 +3765,6 @@
#endif
// init tableView's data source
- resultDataCount = 0;
resultData = [[SPDataStorage alloc] init];
editedRow = -1;
@@ -3787,7 +3775,6 @@
runPrimaryActionButtonAsSelection = nil;
queryLoadTimer = nil;
- resultLoadingCondition = [NSCondition new];
prefs = [NSUserDefaults standardUserDefaults];
@@ -4030,7 +4017,7 @@
if (isWorking) {
pthread_mutex_lock(&resultDataLock);
- if (row < resultDataCount && column < [resultData columnCount]) {
+ if (SPIntS2U(row) < [resultData count] && column < [resultData columnCount]) {
value = SPDataStoragePreviewAtRowAndColumn(resultData, row, column, 150);
}
@@ -4070,7 +4057,6 @@
[NSObject cancelPreviousPerformRequestsWithTarget:customQueryView];
[self clearQueryLoadTimer];
- SPClear(resultLoadingCondition);
SPClear(usedQuery);
SPClear(lastExecutedQuery);
SPClear(resultData);
diff --git a/Source/SPDataStorage.h b/Source/SPDataStorage.h
index bb45f71b..23c7e124 100644
--- a/Source/SPDataStorage.h
+++ b/Source/SPDataStorage.h
@@ -44,6 +44,7 @@
SPMySQLStreamingResultStore *dataStorage;
NSPointerArray *editedRows;
BOOL *unloadedColumns;
+ NSCondition *dataDownloadedLock;
NSUInteger numberOfColumns;
NSUInteger editedRowCount;
@@ -75,6 +76,12 @@
- (NSUInteger) columnCount;
- (BOOL) dataDownloaded;
+/**
+ * This method will block the caller until -dataDownloaded returns YES.
+ * Multiple parallel calls from different threads are possible.
+ */
+- (void) awaitDataDownloaded;
+
/* Delegate callback methods */
- (void)resultStoreDidFinishLoadingData:(SPMySQLStreamingResultStore *)resultStore;
diff --git a/Source/SPDataStorage.m b/Source/SPDataStorage.m
index fca33c0a..44c2dc9d 100644
--- a/Source/SPDataStorage.m
+++ b/Source/SPDataStorage.m
@@ -468,6 +468,13 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore
}
}
+- (void) awaitDataDownloaded
+{
+ [dataDownloadedLock lock];
+ while(![self dataDownloaded]) [dataDownloadedLock wait];
+ [dataDownloadedLock unlock];
+}
+
#pragma mark - Delegate callback methods
/**
@@ -479,6 +486,9 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore
[editedRows setCount:(NSUInteger)[resultStore numberOfRows]];
editedRowCount = [editedRows count];
}
+ [dataDownloadedLock lock];
+ [dataDownloadedLock broadcast];
+ [dataDownloadedLock unlock];
}
/**
@@ -492,6 +502,7 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore
dataStorage = nil;
editedRows = nil;
unloadedColumns = NULL;
+ dataDownloadedLock = [NSCondition new];
numberOfColumns = 0;
editedRowCount = 0;
@@ -504,6 +515,7 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore
@synchronized(self) {
SPClear(dataStorage);
SPClear(editedRows);
+ SPClear(dataDownloadedLock);
if (unloadedColumns) {
free(unloadedColumns), unloadedColumns = NULL;
}