diff options
-rw-r--r-- | Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m | 5 | ||||
-rw-r--r-- | Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m | 5 | ||||
-rw-r--r-- | Interfaces/English.lproj/DBView.xib | 97 | ||||
-rw-r--r-- | Source/SPDataStorage.m | 390 | ||||
-rw-r--r-- | Source/SPDatabaseStructure.m | 1 | ||||
-rw-r--r-- | Source/SPExtendedTableInfo.m | 7 | ||||
-rw-r--r-- | Source/SPQueryFavoriteManager.m | 2 | ||||
-rw-r--r-- | Source/SPTableCopy.m | 11 |
8 files changed, 241 insertions, 277 deletions
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m index e5a48d48..d96ebe52 100644 --- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m +++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m @@ -296,7 +296,7 @@ [self _lockConnection]; unsigned long long theAffectedRowCount; - while (queryAttemptsAllowed > 0) { + do { // While recording the overall execution time (including network lag!), run // the raw query @@ -342,8 +342,7 @@ [self _lockConnection]; NSAssert(mySQLConnection != NULL, @"mySQLConnection has disappeared while checking it!"); - queryAttemptsAllowed--; - } + } while (--queryAttemptsAllowed > 0); id theResult = nil; diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m index e102c24d..286296af 100644 --- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m +++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection.m @@ -928,7 +928,10 @@ static uint64_t _elapsedMicroSecondsSinceAbsoluteTime(uint64_t comparisonTime) uint64_t disconnectStartTime_t = mach_absolute_time(); while (![self _tryLockConnection]) { usleep(100000); - if (_elapsedSecondsSinceAbsoluteTime(disconnectStartTime_t) > 10) break; + if (_elapsedSecondsSinceAbsoluteTime(disconnectStartTime_t) > 10) { + NSLog(@"%s: Could not acquire connection lock within time limit (10s). Forcing unlock!",__PRETTY_FUNCTION__); + break; + } } [self _unlockConnection]; [self _cancelKeepAlives]; diff --git a/Interfaces/English.lproj/DBView.xib b/Interfaces/English.lproj/DBView.xib index dd04904d..7ffa8fc8 100644 --- a/Interfaces/English.lproj/DBView.xib +++ b/Interfaces/English.lproj/DBView.xib @@ -5403,79 +5403,6 @@ <int key="NSCellFlags">68157504</int> <int key="NSCellFlags2">272761856</int> <reference key="NSSupport" ref="26"/> - <object class="NSNumberFormatter" key="NSFormatter" id="597232718"> - <dictionary class="NSMutableDictionary" key="NS.attributes"> - <boolean value="YES" key="allowsFloats"/> - <boolean value="NO" key="alwaysShowsDecimalSeparator"/> - <string key="currencyDecimalSeparator">.</string> - <string key="decimalSeparator">.</string> - <string key="exponentSymbol">E</string> - <integer value="0" key="formatWidth"/> - <integer value="1040" key="formatterBehavior"/> - <boolean value="NO" key="generatesDecimalNumbers"/> - <string key="groupingSeparator">,</string> - <integer value="3" key="groupingSize"/> - <boolean value="YES" key="lenient"/> - <integer value="3" key="maximumFractionDigits"/> - <integer value="309" key="maximumIntegerDigits"/> - <real value="1" key="minimum"/> - <integer value="0" key="minimumFractionDigits"/> - <integer value="1" key="minimumIntegerDigits"/> - <string key="minusSign">-</string> - <string key="negativeFormat">#,##0.###</string> - <string key="negativeInfinitySymbol">-∞</string> - <string key="negativePrefix">-</string> - <string key="negativeSuffix"/> - <string key="nilSymbol"/> - <string key="notANumberSymbol">NaN</string> - <integer value="1" key="numberStyle"/> - <string key="paddingCharacter">*</string> - <integer value="0" key="paddingPosition"/> - <string key="perMillSymbol">‰</string> - <string key="percentSymbol">%</string> - <string key="plusSign">+</string> - <string key="positiveFormat">#,##0.###</string> - <string key="positiveInfinitySymbol">+∞</string> - <string key="positivePrefix"/> - <string key="positiveSuffix"/> - <real value="0.0" key="roundingIncrement"/> - <integer value="4" key="roundingMode"/> - <integer value="0" key="secondaryGroupingSize"/> - <boolean value="YES" key="usesGroupingSeparator"/> - </dictionary> - <string key="NS.positiveformat">#,##0.###</string> - <string key="NS.negativeformat">#,##0.###</string> - <nil key="NS.positiveattrs"/> - <nil key="NS.negativeattrs"/> - <nil key="NS.zero"/> - <object class="NSAttributedString" key="NS.nil"> - <string key="NSString"/> - </object> - <object class="NSAttributedString" key="NS.nan"> - <string key="NSString">NaN</string> - <dictionary key="NSAttributes" id="10305650"/> - </object> - <real value="1" key="NS.min"/> - <object class="NSDecimalNumberPlaceholder" key="NS.max" id="581212392"> - <int key="NS.exponent">0</int> - <int key="NS.length">0</int> - <bool key="NS.negative">YES</bool> - <bool key="NS.compact">NO</bool> - <int key="NS.mantissa.bo">1</int> - <bytes key="NS.mantissa">AAAAAAAAAAAAAAAAAAAAAA</bytes> - </object> - <object class="NSDecimalNumberHandler" key="NS.rounding"> - <int key="NS.roundingmode">3</int> - <bool key="NS.raise.overflow">YES</bool> - <bool key="NS.raise.underflow">YES</bool> - <bool key="NS.raise.dividebyzero">YES</bool> - </object> - <string key="NS.decimal">.</string> - <string key="NS.thousand">,</string> - <bool key="NS.hasthousands">YES</bool> - <bool key="NS.localized">YES</bool> - <bool key="NS.allowsfloats">YES</bool> - </object> <reference key="NSControlView" ref="735808692"/> <reference key="NSBackgroundColor" ref="647098198"/> <reference key="NSTextColor" ref="667308713"/> @@ -8136,10 +8063,17 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8</string> </object> <object class="NSAttributedString" key="NS.nan"> <string key="NSString">NaN</string> - <reference key="NSAttributes" ref="10305650"/> + <dictionary key="NSAttributes"/> </object> <real value="1" key="NS.min"/> - <reference key="NS.max" ref="581212392"/> + <object class="NSDecimalNumberPlaceholder" key="NS.max"> + <int key="NS.exponent">0</int> + <int key="NS.length">0</int> + <bool key="NS.negative">YES</bool> + <bool key="NS.compact">NO</bool> + <int key="NS.mantissa.bo">1</int> + <bytes key="NS.mantissa">AAAAAAAAAAAAAAAAAAAAAA</bytes> + </object> <object class="NSDecimalNumberHandler" key="NS.rounding"> <int key="NS.roundingmode">3</int> <bool key="NS.raise.overflow">YES</bool> @@ -19990,17 +19924,10 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <object class="IBObjectRecord"> <string key="id">5782</string> <reference key="object" ref="105876720"/> - <array class="NSMutableArray" key="children"> - <reference ref="597232718"/> - </array> + <array class="NSMutableArray" key="children"/> <reference key="parent" ref="735808692"/> </object> <object class="IBObjectRecord"> - <string key="id">6879</string> - <reference key="object" ref="597232718"/> - <reference key="parent" ref="105876720"/> - </object> - <object class="IBObjectRecord"> <string key="id">5793</string> <reference key="object" ref="503851323"/> <array class="NSMutableArray" key="children"> @@ -26134,10 +26061,6 @@ AAEAAQAAAT0AAwAAAAEAAgAAAVIAAwAAAAEAAQAAAVMAAwAAAAIAAQABAAAAAA</bytes> <boolean value="NO" key="6877.showNotes"/> <string key="6878.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="NO" key="6878.showNotes"/> - <integer value="1041" key="6879.IBNumberFormatterBehaviorMetadataKey"/> - <boolean value="YES" key="6879.IBNumberFormatterLocalizesFormatMetadataKey"/> - <string key="6879.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> - <boolean value="NO" key="6879.showNotes"/> <string key="6885.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <reference key="6885.IBUserGuides" ref="0"/> <boolean value="NO" key="6885.showNotes"/> diff --git a/Source/SPDataStorage.m b/Source/SPDataStorage.m index bae17111..46db243f 100644 --- a/Source/SPDataStorage.m +++ b/Source/SPDataStorage.m @@ -62,41 +62,46 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) setDataStorage:(SPMySQLStreamingResultStore *)newDataStorage updatingExisting:(BOOL)updateExistingStore { - NSUInteger i; - editedRowCount = 0; - SPClear(editedRows); - @synchronized(self) { - if (unloadedColumns) { - [self _recordClearingUnloadedColumnsAt:mach_absolute_time() from:[NSThread callStackSymbols]]; - free(unloadedColumns), unloadedColumns = NULL; - } - } - - - if (dataStorage) { + SPMySQLStreamingResultStore *oldDataStorage = dataStorage; + if (oldDataStorage) { // If the table is reloading data, link to the current data store for smoother loads if (updateExistingStore) { - [newDataStorage replaceExistingResultStore:dataStorage]; + [newDataStorage replaceExistingResultStore:oldDataStorage]; } - - SPClear(dataStorage); } - dataStorage = [newDataStorage retain]; - [dataStorage setDelegate:self]; + [newDataStorage retain]; - numberOfColumns = [dataStorage numberOfFields]; - editedRows = [NSPointerArray new]; - if ([dataStorage dataDownloaded]) { - [self resultStoreDidFinishLoadingData:dataStorage]; + NSPointerArray *newEditedRows = [[NSPointerArray alloc] init]; + NSUInteger newNumberOfColumns = [newDataStorage numberOfFields]; + BOOL *newUnloadedColumns = calloc(newNumberOfColumns, sizeof(BOOL)); + for (NSUInteger i = 0; i < newNumberOfColumns; i++) { + newUnloadedColumns[i] = NO; } - + + BOOL *oldUnloadedColumns = unloadedColumns; + NSPointerArray *oldEditedRows = editedRows; @synchronized(self) { - unloadedColumns = calloc(numberOfColumns, sizeof(BOOL)); - for (i = 0; i < numberOfColumns; i++) { - unloadedColumns[i] = NO; - } + dataStorage = newDataStorage; + numberOfColumns = newNumberOfColumns; + unloadedColumns = newUnloadedColumns; + editedRowCount = 0; + editedRows = newEditedRows; + } + free(oldUnloadedColumns); + [oldEditedRows release]; + [oldDataStorage release]; + + // the only delegate callback is resultStoreDidFinishLoadingData:. + // We can't set the delegate before exchanging the dataStorage ivar since then + // the message would come from an unknown object. + // But if we set it afterwards, we risk losing the callback event (since it could've + // happened in the meantime) - this is what the following if() is for. + [newDataStorage setDelegate:self]; + + if ([newDataStorage dataDownloaded]) { + [self resultStoreDidFinishLoadingData:newDataStorage]; } } @@ -109,30 +114,30 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (NSMutableArray *) rowContentsAtIndex:(NSUInteger)anIndex { - - // If an edited row exists for the supplied index, return it - if (anIndex < editedRowCount) { - NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, anIndex); - - if (editedRow != NULL) { - return editedRow; - } - } - - // Otherwise, prepare to return the underlying storage row - NSMutableArray *dataArray = SPMySQLResultStoreGetRow(dataStorage, anIndex); - - // Modify unloaded cells as appropriate + SPNotLoaded *notLoaded = [SPNotLoaded notLoaded]; @synchronized(self) { + // If an edited row exists for the supplied index, return it + if (anIndex < editedRowCount) { + NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, anIndex); + + if (editedRow != NULL) { + return editedRow; + } + } + + // Otherwise, prepare to return the underlying storage row + NSMutableArray *dataArray = SPMySQLResultStoreGetRow(dataStorage, anIndex); + + // Modify unloaded cells as appropriate [self _assesUnloadedColumnsIsSet]; for (NSUInteger i = 0; i < numberOfColumns; i++) { if (unloadedColumns[i]) { - CFArraySetValueAtIndex((CFMutableArrayRef)dataArray, i, [SPNotLoaded notLoaded]); + CFArraySetValueAtIndex((CFMutableArrayRef)dataArray, i, notLoaded); } } + + return dataArray; } - - return dataArray; } /** @@ -140,30 +145,31 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (id) cellDataAtRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex { - // If an edited row exists at the supplied index, return it - if (rowIndex < editedRowCount) { - NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); + SPNotLoaded *notLoaded = [SPNotLoaded notLoaded]; + @synchronized(self) { + // If an edited row exists at the supplied index, return it + if (rowIndex < editedRowCount) { + NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); - if (editedRow != NULL) { - return CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex); + if (editedRow != NULL) { + return CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex); + } } - } - // Throw an exception if the column index is out of bounds - if (columnIndex >= numberOfColumns) { - [NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; - } + // Throw an exception if the column index is out of bounds + if (columnIndex >= numberOfColumns) { + [NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; + } - // If the specified column is not loaded, return a SPNotLoaded reference - @synchronized(self) { + // If the specified column is not loaded, return a SPNotLoaded reference [self _assesUnloadedColumnsIsSet]; if (unloadedColumns[columnIndex]) { - return [SPNotLoaded notLoaded]; + return notLoaded; } - } - // Return the content - return SPMySQLResultStoreObjectAtRowAndColumn(dataStorage, rowIndex, columnIndex); + // Return the content + return SPMySQLResultStoreObjectAtRowAndColumn(dataStorage, rowIndex, columnIndex); + } } /** @@ -172,35 +178,35 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (id) cellPreviewAtRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex previewLength:(NSUInteger)previewLength { - - // If an edited row exists at the supplied index, return it - if (rowIndex < editedRowCount) { - NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); - - if (editedRow != NULL) { - id anObject = CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex); - if ([anObject isKindOfClass:[NSString class]] && [(NSString *)anObject length] > 150) { - return ([NSString stringWithFormat:@"%@...", [anObject substringToIndex:147]]); + SPNotLoaded *notLoaded = [SPNotLoaded notLoaded]; + @synchronized(self) { + // If an edited row exists at the supplied index, return it + if (rowIndex < editedRowCount) { + NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); + + if (editedRow != NULL) { + id anObject = CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex); + if ([anObject isKindOfClass:[NSString class]] && [(NSString *)anObject length] > 150) { + return ([NSString stringWithFormat:@"%@...", [anObject substringToIndex:147]]); + } + return anObject; } - return anObject; } - } - // Throw an exception if the column index is out of bounds - if (columnIndex >= numberOfColumns) { - [NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; - } + // Throw an exception if the column index is out of bounds + if (columnIndex >= numberOfColumns) { + [NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; + } - // If the specified column is not loaded, return a SPNotLoaded reference - @synchronized(self) { + // If the specified column is not loaded, return a SPNotLoaded reference [self _assesUnloadedColumnsIsSet]; if (unloadedColumns[columnIndex]) { - return [SPNotLoaded notLoaded]; + return notLoaded; } - } - // Return the content - return SPMySQLResultStorePreviewAtRowAndColumn(dataStorage, rowIndex, columnIndex, previewLength); + // Return the content + return SPMySQLResultStorePreviewAtRowAndColumn(dataStorage, rowIndex, columnIndex, previewLength); + } } /** @@ -208,28 +214,29 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (BOOL) cellIsNullOrUnloadedAtRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex { - // If an edited row exists at the supplied index, check it for a NULL. - if (rowIndex < editedRowCount) { - NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); + @synchronized(self) { + // If an edited row exists at the supplied index, check it for a NULL. + if (rowIndex < editedRowCount) { + NSMutableArray *editedRow = SPDataStorageGetEditedRow(editedRows, rowIndex); - if (editedRow != NULL) { - return [(id)CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex) isNSNull]; + if (editedRow != NULL) { + return [(id)CFArrayGetValueAtIndex((CFArrayRef)editedRow, columnIndex) isNSNull]; + } + } + + // Throw an exception if the column index is out of bounds + if (columnIndex >= numberOfColumns) { + [NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; } - } - // Throw an exception if the column index is out of bounds - if (columnIndex >= numberOfColumns) { - [NSException raise:NSRangeException format:@"Requested storage column (col %llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; - } - @synchronized(self) { [self _assesUnloadedColumnsIsSet]; if (unloadedColumns[columnIndex]) { return YES; } - } - return [dataStorage cellIsNullAtRow:rowIndex column:columnIndex]; + return [dataStorage cellIsNullAtRow:rowIndex column:columnIndex]; + } } #pragma mark - @@ -242,26 +249,29 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len { - NSMutableArray *targetRow = NULL; - - // If the start index is out of bounds, return 0 to indicate end of results - if (state->state >= SPMySQLResultStoreGetRowCount(dataStorage)) return 0; - - // If an edited row exists for the supplied index, use that; otherwise use the underlying - // storage row - if (state->state < editedRowCount) { - targetRow = SPDataStorageGetEditedRow(editedRows, state->state); - } + NSMutableArray *targetRow = nil; + size_t srcObject; + + SPNotLoaded *notLoaded = [SPNotLoaded notLoaded]; + @synchronized(self) { + srcObject = (size_t)dataStorage ^ (size_t)editedRows ^ editedRowCount; + // If the start index is out of bounds, return 0 to indicate end of results + if (state->state >= SPMySQLResultStoreGetRowCount(dataStorage)) return 0; + + // If an edited row exists for the supplied index, use that; otherwise use the underlying + // storage row + if (state->state < editedRowCount) { + targetRow = SPDataStorageGetEditedRow(editedRows, state->state); + } - if (targetRow == NULL) { - targetRow = SPMySQLResultStoreGetRow(dataStorage, state->state); + if (targetRow == nil) { + targetRow = SPMySQLResultStoreGetRow(dataStorage, state->state); - // Modify unloaded cells as appropriate - @synchronized(self) { + // Modify unloaded cells as appropriate [self _assesUnloadedColumnsIsSet]; for (NSUInteger i = 0; i < numberOfColumns; i++) { if (unloadedColumns[i]) { - CFArraySetValueAtIndex((CFMutableArrayRef)targetRow, i, [SPNotLoaded notLoaded]); + CFArraySetValueAtIndex((CFMutableArrayRef)targetRow, i, notLoaded); } } } @@ -272,7 +282,7 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore state->state += 1; state->itemsPtr = stackbuf; - state->mutationsPtr = (unsigned long *)self; + state->mutationsPtr = (unsigned long *)srcObject; return 1; } @@ -287,16 +297,17 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) addRowWithContents:(NSMutableArray *)aRow { + @synchronized(self) { + // Verify the row is of the correct length + [self _checkNewRow:aRow]; - // Verify the row is of the correct length - [self _checkNewRow:aRow]; - - // Add the new row to the editable store - [editedRows addPointer:aRow]; - editedRowCount++; + // Add the new row to the editable store + [editedRows addPointer:aRow]; + editedRowCount++; - // Update the underlying store as well to keep counts correct - [dataStorage addDummyRow]; + // Update the underlying store as well to keep counts correct + [dataStorage addDummyRow]; + } } /** @@ -306,27 +317,29 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) insertRowContents:(NSMutableArray *)aRow atIndex:(NSUInteger)anIndex { - unsigned long long numberOfRows = SPMySQLResultStoreGetRowCount(dataStorage); + @synchronized(self) { + unsigned long long numberOfRows = SPMySQLResultStoreGetRowCount(dataStorage); - // Verify the row is of the correct length - [self _checkNewRow:aRow]; + // Verify the row is of the correct length + [self _checkNewRow:aRow]; - // Throw an exception if the index is out of bounds - if (anIndex > numberOfRows) { - [NSException raise:NSRangeException format:@"Requested storage index (%llu) beyond bounds (%llu)", (unsigned long long)anIndex, numberOfRows]; - } + // Throw an exception if the index is out of bounds + if (anIndex > numberOfRows) { + [NSException raise:NSRangeException format:@"Requested storage index (%llu) beyond bounds (%llu)", (unsigned long long)anIndex, numberOfRows]; + } - // If "inserting" at the end of the array just add a row - if (anIndex == numberOfRows) { - return [self addRowWithContents:aRow]; - } + // If "inserting" at the end of the array just add a row + if (anIndex == numberOfRows) { + return [self addRowWithContents:aRow]; + } - // Add the new row to the editable store - [editedRows insertPointer:aRow atIndex:anIndex]; - editedRowCount++; + // Add the new row to the editable store + [editedRows insertPointer:aRow atIndex:anIndex]; + editedRowCount++; - // Update the underlying store to keep counts and indices correct - [dataStorage insertDummyRowAtIndex:anIndex]; + // Update the underlying store to keep counts and indices correct + [dataStorage insertDummyRowAtIndex:anIndex]; + } } /** @@ -334,8 +347,10 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) replaceRowAtIndex:(NSUInteger)anIndex withRowContents:(NSMutableArray *)aRow { - [self _checkNewRow:aRow]; - [editedRows replacePointerAtIndex:anIndex withPointer:aRow]; + @synchronized(self) { + [self _checkNewRow:aRow]; + [editedRows replacePointerAtIndex:anIndex withPointer:aRow]; + } } /** @@ -343,16 +358,18 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) replaceObjectInRow:(NSUInteger)rowIndex column:(NSUInteger)columnIndex withObject:(id)anObject { - NSMutableArray *editableRow = NULL; + NSMutableArray *editableRow = nil; - if (rowIndex < editedRowCount) { - editableRow = SPDataStorageGetEditedRow(editedRows, rowIndex); - } + @synchronized(self) { + if (rowIndex < editedRowCount) { + editableRow = SPDataStorageGetEditedRow(editedRows, rowIndex); + } - // Make sure that the row in question is editable - if (editableRow == NULL) { - editableRow = [self rowContentsAtIndex:rowIndex]; - [editedRows replacePointerAtIndex:rowIndex withPointer:editableRow]; + // Make sure that the row in question is editable + if (editableRow == nil) { + editableRow = [self rowContentsAtIndex:rowIndex]; + [editedRows replacePointerAtIndex:rowIndex withPointer:editableRow]; + } } // Modify the cell @@ -364,18 +381,19 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) removeRowAtIndex:(NSUInteger)anIndex { + @synchronized(self) { + // Throw an exception if the index is out of bounds + if (anIndex >= SPMySQLResultStoreGetRowCount(dataStorage)) { + [NSException raise:NSRangeException format:@"Requested storage index (%llu) beyond bounds (%llu)", (unsigned long long)anIndex, SPMySQLResultStoreGetRowCount(dataStorage)]; + } - // Throw an exception if the index is out of bounds - if (anIndex >= SPMySQLResultStoreGetRowCount(dataStorage)) { - [NSException raise:NSRangeException format:@"Requested storage index (%llu) beyond bounds (%llu)", (unsigned long long)anIndex, SPMySQLResultStoreGetRowCount(dataStorage)]; - } - - // Remove the row from the edited list and underlying storage - if (anIndex < editedRowCount) { - editedRowCount--; - [editedRows removePointerAtIndex:anIndex]; + // Remove the row from the edited list and underlying storage + if (anIndex < editedRowCount) { + editedRowCount--; + [editedRows removePointerAtIndex:anIndex]; + } + [dataStorage removeRowAtIndex:anIndex]; } - [dataStorage removeRowAtIndex:anIndex]; } /** @@ -384,19 +402,20 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) removeRowsInRange:(NSRange)rangeToRemove { + @synchronized(self) { + // Throw an exception if the range is out of bounds + if (NSMaxRange(rangeToRemove) > SPMySQLResultStoreGetRowCount(dataStorage)) { + [NSException raise:NSRangeException format:@"Requested storage index (%llu) beyond bounds (%llu)", (unsigned long long)(NSMaxRange(rangeToRemove)), SPMySQLResultStoreGetRowCount(dataStorage)]; + } - // Throw an exception if the range is out of bounds - if (NSMaxRange(rangeToRemove) > SPMySQLResultStoreGetRowCount(dataStorage)) { - [NSException raise:NSRangeException format:@"Requested storage index (%llu) beyond bounds (%llu)", (unsigned long long)(NSMaxRange(rangeToRemove)), SPMySQLResultStoreGetRowCount(dataStorage)]; - } - - // Remove the rows from the edited list and underlying storage - NSUInteger i = MIN(editedRowCount, NSMaxRange(rangeToRemove)); - while (--i >= rangeToRemove.location) { - editedRowCount--; - [editedRows removePointerAtIndex:i]; + // Remove the rows from the edited list and underlying storage + NSUInteger i = MIN(editedRowCount, NSMaxRange(rangeToRemove)); + while (--i >= rangeToRemove.location) { + editedRowCount--; + [editedRows removePointerAtIndex:i]; + } + [dataStorage removeRowsInRange:rangeToRemove]; } - [dataStorage removeRowsInRange:rangeToRemove]; } /** @@ -404,9 +423,11 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) removeAllRows { - editedRowCount = 0; - [editedRows setCount:0]; - [dataStorage removeAllRows]; + @synchronized(self) { + editedRowCount = 0; + [editedRows setCount:0]; + [dataStorage removeAllRows]; + } } #pragma mark - Unloaded columns @@ -417,10 +438,10 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void) setColumnAsUnloaded:(NSUInteger)columnIndex { - if (columnIndex >= numberOfColumns) { - [NSException raise:NSRangeException format:@"Invalid column set as unloaded; requested column index (%llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; - } @synchronized(self) { + if (columnIndex >= numberOfColumns) { + [NSException raise:NSRangeException format:@"Invalid column set as unloaded; requested column index (%llu) beyond bounds (%llu)", (unsigned long long)columnIndex, (unsigned long long)numberOfColumns]; + } [self _assesUnloadedColumnsIsSet]; unloadedColumns[columnIndex] = YES; } @@ -433,7 +454,9 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (NSUInteger) count { - return (NSUInteger)[dataStorage numberOfRows]; + @synchronized(self) { + return (NSUInteger)[dataStorage numberOfRows]; + } } /** @@ -441,7 +464,9 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (NSUInteger) columnCount { - return numberOfColumns; + @synchronized(self) { + return numberOfColumns; + } } /** @@ -449,7 +474,9 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (BOOL) dataDownloaded { - return !dataStorage || [dataStorage dataDownloaded]; + @synchronized(self) { + return !dataStorage || [dataStorage dataDownloaded]; + } } #pragma mark - Delegate callback methods @@ -459,8 +486,10 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ - (void)resultStoreDidFinishLoadingData:(SPMySQLStreamingResultStore *)resultStore { - [editedRows setCount:(NSUInteger)[resultStore numberOfRows]]; - editedRowCount = [editedRows count]; + @synchronized(self) { + [editedRows setCount:(NSUInteger)[resultStore numberOfRows]]; + editedRowCount = [editedRows count]; + } } /** @@ -468,7 +497,8 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore */ #pragma mark - -- (id) init { +- (id) init +{ if ((self = [super init])) { dataStorage = nil; editedRows = nil; @@ -483,10 +513,11 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore return self; } -- (void) dealloc { - SPClear(dataStorage); - SPClear(editedRows); +- (void) dealloc +{ @synchronized(self) { + SPClear(dataStorage); + SPClear(editedRows); if (unloadedColumns) { [self _recordClearingUnloadedColumnsAt:mach_absolute_time() from:[NSThread callStackSymbols]]; free(unloadedColumns), unloadedColumns = NULL; @@ -506,6 +537,7 @@ static inline NSMutableArray* SPDataStorageGetEditedRow(NSPointerArray* rowStore @implementation SPDataStorage (PrivateAPI) +// DO NOT CALL THIS METHOD UNLESS YOU CURRENTLY HAVE A LOCK ON SELF!!! - (void) _checkNewRow:(NSMutableArray *)aRow { if ([aRow count] != numberOfColumns) { diff --git a/Source/SPDatabaseStructure.m b/Source/SPDatabaseStructure.m index a4663268..b1bed3c9 100644 --- a/Source/SPDatabaseStructure.m +++ b/Source/SPDatabaseStructure.m @@ -275,6 +275,7 @@ // Set up the database as an empty mutable dictionary ready for tables, and store a reference [queriedStructure setObject:[NSMutableDictionary dictionary] forKey:db_id]; NSMutableDictionary *databaseStructure = [queriedStructure objectForKey:db_id]; + structureWasUpdated = YES; NSUInteger uniqueCounter = 0; // used to make field data unique SPMySQLResult *theResult; diff --git a/Source/SPExtendedTableInfo.m b/Source/SPExtendedTableInfo.m index 26574621..e2f38a69 100644 --- a/Source/SPExtendedTableInfo.m +++ b/Source/SPExtendedTableInfo.m @@ -224,7 +224,11 @@ static NSString *SPMySQLCommentField = @"Comment"; { [tableRowAutoIncrement setEditable:NO]; - [tableSourceInstance takeAutoIncrementFrom:tableRowAutoIncrement]; + NSNumberFormatter *fmt = [[[NSNumberFormatter alloc] init] autorelease]; + [fmt setNumberStyle:NSNumberFormatterDecimalStyle]; + NSNumber *value = [fmt numberFromString:[tableRowAutoIncrement stringValue]]; + + [tableSourceInstance setAutoIncrementTo:value]; } - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command @@ -232,6 +236,7 @@ static NSString *SPMySQLCommentField = @"Comment"; // Listen to ESC to abort editing of auto increment input field if (command == @selector(cancelOperation:) && control == tableRowAutoIncrement) { [tableRowAutoIncrement abortEditing]; + [tableRowAutoIncrement setEditable:NO]; return YES; } diff --git a/Source/SPQueryFavoriteManager.m b/Source/SPQueryFavoriteManager.m index 5857b1b7..542184c4 100644 --- a/Source/SPQueryFavoriteManager.m +++ b/Source/SPQueryFavoriteManager.m @@ -488,7 +488,7 @@ #ifndef SP_CODA - (IBAction)showHelp:(id)sender { - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:NSLocalizedString(@"http://www.sequelpro.com/docs/Query_Favorites", @"Localized help page for query favourites - do not localize if no translated webpage is available")]]; + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:NSLocalizedString(@"http://www.sequelpro.com/docs/Working_with_Query_Favorites", @"Localized help page for query favourites - do not localize if no translated webpage is available")]]; } #endif diff --git a/Source/SPTableCopy.m b/Source/SPTableCopy.m index cd3fc42e..07f03846 100644 --- a/Source/SPTableCopy.m +++ b/Source/SPTableCopy.m @@ -44,9 +44,9 @@ - (BOOL)copyTable:(NSString *)tableName from:(NSString *)sourceDB to:(NSString *)targetDB { NSString *createTableResult = [self _createTableStatementFor:tableName inDatabase:sourceDB]; - NSMutableString *createTableStatement = [[NSMutableString alloc] initWithString:createTableResult]; - if ([[createTableStatement substringToIndex:12] isEqualToString:@"CREATE TABLE"]) { + if ([createTableResult hasPrefix:@"CREATE TABLE"]) { + NSMutableString *createTableStatement = [[NSMutableString alloc] initWithString:createTableResult]; // Add the target DB name and the separator dot after "CREATE TABLE ". [createTableStatement insertString:@"." atIndex:13]; @@ -59,8 +59,6 @@ return ![connection queryErrored]; } - [createTableStatement release]; - return NO; } @@ -151,7 +149,10 @@ SPMySQLResult *theResult = [connection queryString:showCreateTableStatment]; - return [theResult numberOfRows] > 0 ? [[theResult getRowAsArray] objectAtIndex:1] : @""; + if([theResult numberOfRows] > 0) return [[theResult getRowAsArray] objectAtIndex:1]; + + NSLog(@"query <%@> failed to return the expected result.\n Error state: %@ (%lu)",showCreateTableStatment,[connection lastErrorMessage],[connection lastErrorID]); + return nil; } @end |