diff options
author | rowanbeentje <rowan@beent.je> | 2012-02-23 02:13:56 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2012-02-23 02:13:56 +0000 |
commit | 05f1612cbb7e33cf9135a346fc2505cc0e87e853 (patch) | |
tree | 785824be4e44a61389271343d958851fa4ff7dd0 /Source/SPCustomQuery.m | |
parent | a889340b9cb1eca0d3ff022e8e6e2c718480bf44 (diff) | |
download | sequelpro-05f1612cbb7e33cf9135a346fc2505cc0e87e853.tar.gz sequelpro-05f1612cbb7e33cf9135a346fc2505cc0e87e853.tar.bz2 sequelpro-05f1612cbb7e33cf9135a346fc2505cc0e87e853.zip |
Warning: this branch commit is largely untested, and known to throw exceptions as database structure retrieval is currently missing!
Further work on SPMySQLFramework integration:
- Improve SPMySQL framework build settings including correct ppc builds and a Distribution configuration for the build distributions to match
- Add new convenience querying and result methods to the framework
- Amend Sequel Pro source to use the new SPMySQL.framework methods everywhere, replacing MCPKit methods where they differ and improving some functions
- Remove MCPKit from the source
- Fix a number of warnings on Release-style builds
Diffstat (limited to 'Source/SPCustomQuery.m')
-rw-r--r-- | Source/SPCustomQuery.m | 129 |
1 files changed, 64 insertions, 65 deletions
diff --git a/Source/SPCustomQuery.m b/Source/SPCustomQuery.m index 61cac5f6..da15da11 100644 --- a/Source/SPCustomQuery.m +++ b/Source/SPCustomQuery.m @@ -25,6 +25,7 @@ #import "SPCustomQuery.h" #import "SPSQLParser.h" +#import "SPMySQL.h" #ifndef SP_REFACTOR /* headers */ #import "SPGrowlController.h" #endif @@ -47,6 +48,7 @@ #import "SPGeometryDataView.h" #import "SPAppController.h" #import "SPBundleHTMLOutputController.h" +#include <pthread.h> #ifndef SP_REFACTOR /* headers */ #import <BWToolkitFramework/BWToolkitFramework.h> @@ -540,7 +542,7 @@ /** * Toggle whether the query info pane is visible. */ -- (IBAction)toggleQueryInfoPaneCollapse:(id)sender +- (IBAction)toggleQueryInfoPaneCollapse:(NSButton *)sender { [queryInfoPaneSplitView toggleCollapse:sender]; @@ -585,12 +587,12 @@ - (void)performQueriesTask:(NSDictionary *)taskArguments { - NSAutoreleasePool *queryRunningPool = [[NSAutoreleasePool alloc] init]; - NSArray *queries = [taskArguments objectForKey:@"queries"]; - MCPStreamingResult *streamingResult = nil; - NSMutableString *errors = [NSMutableString string]; - SEL callbackMethod = NULL; - NSString *taskButtonString; + NSAutoreleasePool *queryRunningPool = [[NSAutoreleasePool alloc] init]; + NSArray *queries = [taskArguments objectForKey:@"queries"]; + SPMySQLFastStreamingResult *streamingResult = nil; + NSMutableString *errors = [NSMutableString string]; + SEL callbackMethod = NULL; + NSString *taskButtonString; NSUInteger i, totalQueriesRun = 0, totalAffectedRows = 0; double executionTime = 0; @@ -627,7 +629,7 @@ } // Disable automatic query retries on failure for the custom queries - [mySQLConnection setAllowQueryRetries:NO]; + [mySQLConnection setRetryQueriesOnConnectionFailure:NO]; NSUInteger queryCount = [queries count]; NSMutableArray *tempQueries = [NSMutableArray arrayWithCapacity:queryCount]; @@ -659,16 +661,16 @@ // Run the query, timing execution (note this also includes network and overhead) streamingResult = [[mySQLConnection streamingQueryString:query] retain]; - executionTime += [mySQLConnection lastQueryExecutionTime]; + executionTime += [streamingResult queryExecutionTime]; totalQueriesRun++; // If this is the last query, retrieve and store the result; otherwise, // discard the result without fully loading. - if (totalQueriesRun == queryCount || [mySQLConnection queryCancelled]) { + if (totalQueriesRun == queryCount || [mySQLConnection lastQueryWasCancelled]) { // Retrieve and cache the column definitions for the result array if (cqColumnDefinition) [cqColumnDefinition release]; - cqColumnDefinition = [[streamingResult fetchResultFieldsStructure] retain]; + cqColumnDefinition = [[streamingResult fieldDefinitions] retain]; if(!reloadingExistingResult) { [[self onMainThread] updateTableView]; @@ -695,24 +697,24 @@ } // Record any affected rows - if ( [mySQLConnection affectedRows] != (my_ulonglong)~0 ) - totalAffectedRows += (NSUInteger)[mySQLConnection affectedRows]; - else if ( [streamingResult numOfRows] ) - totalAffectedRows += (NSUInteger)[streamingResult numOfRows]; + if ( [mySQLConnection rowsAffectedByLastQuery] != (unsigned long long)~0 ) + totalAffectedRows += (NSUInteger)[mySQLConnection rowsAffectedByLastQuery]; + else if ( [streamingResult numberOfRows] ) + totalAffectedRows += (NSUInteger)[streamingResult numberOfRows]; [streamingResult release]; // Store any error messages - if ([mySQLConnection queryErrored] || [mySQLConnection queryCancelled]) { + if ([mySQLConnection queryErrored] || [mySQLConnection lastQueryWasCancelled]) { NSString *errorString; - if ([mySQLConnection queryCancelled]) { - if ([mySQLConnection queryCancellationUsedReconnect]) + if ([mySQLConnection lastQueryWasCancelled]) { + if ([mySQLConnection lastQueryWasCancelledUsingReconnect]) errorString = NSLocalizedString(@"Query cancelled. Please note that to cancel the query the connection had to be reset; transactions and connection variables were reset.", @"Query cancel by resetting connection error"); else errorString = NSLocalizedString(@"Query cancelled.", @"Query cancelled error"); } else { - errorString = [mySQLConnection getLastErrorMessage]; + errorString = [mySQLConnection lastErrorMessage]; } // If the query errored, append error to the error log for display at the end @@ -729,7 +731,7 @@ [[errorText onMainThread] setString:errors]; // ask the user to continue after detecting an error - if (![mySQLConnection queryCancelled]) { + if (![mySQLConnection lastQueryWasCancelled]) { [tableDocumentInstance setTaskIndicatorShouldAnimate:NO]; SPBeginWaitingAlertSheet(@"title", @@ -738,7 +740,7 @@ @selector(sheetDidEnd:returnCode:contextInfo:), @"runAllContinueStopSheet", NSLocalizedString(@"MySQL Error", @"mysql error message"), - [mySQLConnection getLastErrorMessage], + [mySQLConnection lastErrorMessage], &runAllContinueStopSheetReturnCode ); [tableDocumentInstance setTaskIndicatorShouldAnimate:YES]; @@ -771,7 +773,7 @@ databaseWasChanged = YES; } // If the query was cancelled, end all queries. - if ([mySQLConnection queryCancelled]) break; + if ([mySQLConnection lastQueryWasCancelled]) break; } // Reload table list if at least one query began with drop, alter, rename, or create @@ -800,7 +802,7 @@ if ( !queryCount ) { streamingResult = [mySQLConnection streamingQueryString:@""]; [streamingResult cancelResultLoad]; - [errors setString:[mySQLConnection getLastErrorMessage]]; + [errors setString:[mySQLConnection lastErrorMessage]]; } // add query to history @@ -817,7 +819,7 @@ // Set up the status string NSString *statusString = nil; NSString *statusErrorString = [errors length]?NSLocalizedString(@"Errors", @"Errors title"):NSLocalizedString(@"No errors", @"No errors title"); - if ( [mySQLConnection queryCancelled] ) { + if ( [mySQLConnection lastQueryWasCancelled] ) { if (totalQueriesRun > 1) { statusString = [NSString stringWithFormat:NSLocalizedString(@"%@; Cancelled in query %ld, after %@", @"text showing multiple queries were cancelled"), statusErrorString, @@ -862,7 +864,7 @@ [[affectedRowsText onMainThread] setStringValue:statusString]; // Restore automatic query retries - [mySQLConnection setAllowQueryRetries:YES]; + [mySQLConnection setRetryQueriesOnConnectionFailure:YES]; #ifndef SP_REFACTOR /* [tableDocumentInstance setQueryMode:] */ [tableDocumentInstance setQueryMode:SPInterfaceQueryMode]; @@ -937,9 +939,8 @@ /** * Processes a supplied streaming result set, loading it into the data array. */ -- (void)processResultIntoDataStorage:(MCPStreamingResult *)theResult +- (void)processResultIntoDataStorage:(SPMySQLFastStreamingResult *)theResult { - NSArray *tempRow; NSAutoreleasePool *dataLoadingPool; // Remove all items from the table @@ -951,7 +952,7 @@ // Set the column count on the data store before setting up anything else - // ensures that SPDataStorage is set up for timer-driven data loads - [resultData setColumnCount:[theResult numOfFields]]; + [resultData setColumnCount:[theResult numberOfFields]]; // Set up the table updates timer [[self onMainThread] initQueryLoadTimer]; @@ -960,10 +961,10 @@ dataLoadingPool = [[NSAutoreleasePool alloc] init]; // Loop through the result rows as they become available - while ((tempRow = [theResult fetchNextRowAsArray])) { + for (NSArray *eachRow in theResult) { pthread_mutex_lock(&resultDataLock); - SPDataStorageAddRow(resultData, tempRow); + SPDataStorageAddRow(resultData, eachRow); resultDataCount++; pthread_mutex_unlock(&resultDataLock); @@ -1289,7 +1290,7 @@ NSInteger firstErrorOccuredInQuery = [[errorDetails objectForKey:@"firstErrorQueryNumber"] integerValue]; // If errors occur, display them - if ( [mySQLConnection queryCancelled] || ([errorsString length] && !queryIsTableSorter)) { + if ( [mySQLConnection lastQueryWasCancelled] || ([errorsString length] && !queryIsTableSorter)) { // set the error text [errorText setString:[errorsString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; @@ -1300,7 +1301,7 @@ NSRange errorLineNumberRange = [errorsString rangeOfRegex:@"([0-9]+)[^0-9]*$" options:RKLNoOptions inRange:NSMakeRange(0, [errorsString length]) capture:1L error:nil]; // if error ID 1064 and a line number was found - if([mySQLConnection getLastErrorID] == 1064 && errorLineNumberRange.length) + if([mySQLConnection lastErrorID] == 1064 && errorLineNumberRange.length) { // Get the line number NSUInteger errorAtLine = [[errorsString substringWithRange:errorLineNumberRange] integerValue]; @@ -1508,7 +1509,7 @@ /** * Sets the connection (received from SPDatabaseDocument) and makes things that have to be done only once */ -- (void)setConnection:(MCPConnection *)theConnection +- (void)setConnection:(SPMySQLConnection *)theConnection { mySQLConnection = theConnection; currentQueryRanges = nil; @@ -1764,7 +1765,7 @@ [tableDocumentInstance startTaskWithDescription:NSLocalizedString(@"Checking field data for editing...", @"checking field data for editing task description")]; // Actual check whether field can be identified bijectively - MCPResult *tempResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT COUNT(1) FROM %@.%@ %@", + SPMySQLResult *tempResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SELECT COUNT(1) FROM %@.%@ %@", [[columnDefinition objectForKey:@"db"] backtickQuotedString], [tableForColumn backtickQuotedString], fieldIDQueryStr]]; @@ -1774,7 +1775,7 @@ return [NSArray arrayWithObjects:[NSNumber numberWithInteger:-1], @"", nil]; } - NSArray *tempRow = [tempResult fetchRowAsArray]; + NSArray *tempRow = [tempResult getRowAsArray]; if([tempRow count] && [[tempRow objectAtIndex:0] integerValue] > 1) { // try to identify the cell by using blob data @@ -1794,7 +1795,7 @@ return [NSArray arrayWithObjects:[NSNumber numberWithInteger:-1], @"", nil]; } - tempRow = [tempResult fetchRowAsArray]; + tempRow = [tempResult getRowAsArray]; if([tempRow count] && [[tempRow objectAtIndex:0] integerValue] < 1) { [tableDocumentInstance endTask]; @@ -1817,7 +1818,6 @@ - (NSString *)argumentForRow:(NSUInteger)rowIndex ofTable:(NSString *)tableForColumn andDatabase:(NSString *)database includeBlobs:(BOOL)includeBlobs { NSArray *dataRow; - NSDictionary *theRow; id field; NSMutableArray *argumentParts = [NSMutableArray array]; @@ -1832,17 +1832,14 @@ dataRow = [resultData rowContentsAtIndex:rowIndex]; // Get the primary key if there is one, using any columns present within it - MCPResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@.%@", + SPMySQLResult *theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"SHOW COLUMNS FROM %@.%@", [database backtickQuotedString], [tableForColumn backtickQuotedString]]]; [theResult setReturnDataAsStrings:YES]; - if ([theResult numOfRows]) [theResult dataSeek:0]; NSMutableArray *primaryColumnsInSpecifiedTable = [NSMutableArray array]; - NSUInteger i; - for ( i = 0 ; i < [theResult numOfRows] ; i++ ) { - theRow = [theResult fetchRowAsDictionary]; - if ( [[theRow objectForKey:@"Key"] isEqualToString:@"PRI"] ) { + for (NSDictionary *eachRow in theResult) { + if ( [[eachRow objectForKey:@"Key"] isEqualToString:@"PRI"] ) { for (field in columnsInSpecifiedTable) { - if([[field objectForKey:@"org_name"] isEqualToString:[theRow objectForKey:@"Field"]]) { + if([[field objectForKey:@"org_name"] isEqualToString:[eachRow objectForKey:@"Field"]]) { [primaryColumnsInSpecifiedTable addObject:field]; } } @@ -1855,7 +1852,7 @@ // Build up the argument for (field in columnsToQuery) { id aValue = [dataRow objectAtIndex:[[field objectForKey:@"datacolumnindex"] integerValue]]; - if ([aValue isKindOfClass:[NSNull class]] || [aValue isNSNull]) { + if ([aValue isNSNull]) { [argumentParts addObject:[NSString stringWithFormat:@"%@ IS NULL", [[field objectForKey:@"org_name"] backtickQuotedString]]]; } else { NSString *fieldTypeGrouping = [field objectForKey:@"typegrouping"]; @@ -1875,14 +1872,14 @@ [argumentParts addObject:[NSString stringWithFormat:@"%@=b'%@'", [[field objectForKey:@"org_name"] backtickQuotedString], [aValue description]]]; } else if ([fieldTypeGrouping isEqualToString:@"geometry"]) { - [argumentParts addObject:[NSString stringWithFormat:@"%@=X'%@'", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareBinaryData:[aValue data]]]]; + [argumentParts addObject:[NSString stringWithFormat:@"%@=%@", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection escapeAndQuoteData:[aValue data]]]]; } // BLOB/TEXT data else if ([aValue isKindOfClass:[NSData class]]) { - [argumentParts addObject:[NSString stringWithFormat:@"%@=X'%@'", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareBinaryData:aValue]]]; + [argumentParts addObject:[NSString stringWithFormat:@"%@=%@", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection escapeAndQuoteData:aValue]]]; } else { - [argumentParts addObject:[NSString stringWithFormat:@"%@='%@'", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection prepareString:aValue]]]; + [argumentParts addObject:[NSString stringWithFormat:@"%@=%@", [[field objectForKey:@"org_name"] backtickQuotedString], [mySQLConnection escapeAndQuoteString:aValue]]]; } } } @@ -1919,11 +1916,11 @@ NSString *newObject = nil; if ( [anObject isKindOfClass:[NSCalendarDate class]] ) { - newObject = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[anObject description]]]; + newObject = [mySQLConnection escapeAndQuoteString:[anObject description]]; } else if ( [anObject isKindOfClass:[NSNumber class]] ) { newObject = [anObject stringValue]; } else if ( [anObject isKindOfClass:[NSData class]] ) { - newObject = [NSString stringWithFormat:@"X'%@'", [mySQLConnection prepareBinaryData:anObject]]; + newObject = [mySQLConnection escapeAndQuoteData:anObject]; } else { if ( [[anObject description] isEqualToString:@"CURRENT_TIMESTAMP"] ) { newObject = @"CURRENT_TIMESTAMP"; @@ -1940,7 +1937,7 @@ && [[anObject description] isEqualToString:@"NOW()"]) { newObject = @"NOW()"; } else { - newObject = [NSString stringWithFormat:@"'%@'", [mySQLConnection prepareString:[anObject description]]]; + newObject = [mySQLConnection escapeAndQuoteString:[anObject description]]; } } @@ -1952,13 +1949,13 @@ // Check for errors while UPDATE if ([mySQLConnection queryErrored]) { SPBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), NSLocalizedString(@"Cancel", @"cancel button"), nil, [tableDocumentInstance parentWindow], self, nil, nil, - [NSString stringWithFormat:NSLocalizedString(@"Couldn't write field.\nMySQL said: %@", @"message of panel when error while updating field to db"), [mySQLConnection getLastErrorMessage]]); + [NSString stringWithFormat:NSLocalizedString(@"Couldn't write field.\nMySQL said: %@", @"message of panel when error while updating field to db"), [mySQLConnection lastErrorMessage]]); return; } // This shouldn't happen – for safety reasons - if ( ![mySQLConnection affectedRows] ) { + if ( ![mySQLConnection rowsAffectedByLastQuery] ) { #ifndef SP_REFACTOR if ( [prefs boolForKey:SPShowNoAffectedRowsError] ) { SPBeginAlertSheet(NSLocalizedString(@"Warning", @"warning"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [tableDocumentInstance parentWindow], self, nil, nil, @@ -2335,7 +2332,7 @@ return nil; } } - else if ([theValue isKindOfClass:[MCPGeometryData class]]) { + else if ([theValue isKindOfClass:[SPMySQLGeometryData class]]) { SPGeometryDataView *v = [[SPGeometryDataView alloc] initWithCoordinates:[theValue coordinates]]; image = [v thumbnailImage]; if(image) { @@ -3070,7 +3067,7 @@ if(![searchString length]) return @""; NSRange aRange; - MCPResult *theResult = nil; + SPMySQLResult *theResult = nil; NSDictionary *tableDetails; NSMutableString *theHelp = [NSMutableString string]; @@ -3089,14 +3086,16 @@ return SP_HELP_NOT_AVAILABLE; } // nothing found? - if(![theResult numOfRows]) { + if(![theResult numberOfRows]) { + // try to search via: HELP 'searchString%' theResult = [mySQLConnection queryString:[NSString stringWithFormat:@"HELP '%@%%'", [searchString stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"]]]; + // really nothing found? - if(![theResult numOfRows]) + if(![theResult numberOfRows]) return @""; } - tableDetails = [[NSDictionary alloc] initWithDictionary:[theResult fetchRowAsDictionary]]; + tableDetails = [[NSDictionary alloc] initWithDictionary:[theResult getRowAsDictionary]]; if ([tableDetails objectForKey:@"description"]) { // one single help topic found if ([tableDetails objectForKey:@"name"]) { @@ -3171,9 +3170,9 @@ } } else { // list all found topics - NSUInteger i; - NSUInteger r = (NSUInteger)[theResult numOfRows]; - if (r) [theResult dataSeek:0]; + NSUInteger r = (NSUInteger)[theResult numberOfRows]; + if (r) [theResult seekToRow:0]; + // check if HELP 'contents' is called if(![searchString isEqualToString:SP_HELP_TOC_SEARCH_STRING]) [theHelp appendFormat:@"<br><i>%@ “%@”</i><br>", NSLocalizedString(@"Help topics for", @"help topics for"), searchString]; @@ -3182,9 +3181,9 @@ // iterate through all found rows and print them as HTML ul/li list [theHelp appendString:@"<ul>"]; - for ( i = 0 ; i < r ; i++ ) { - NSArray *anArray = [theResult fetchRowAsArray]; - NSString *topic = [anArray objectAtIndex:[anArray count]-2]; + [theResult setDefaultRowReturnType:SPMySQLResultRowAsArray]; + for (NSArray *eachRow in theResult) { + NSString *topic = [eachRow objectAtIndex:[eachRow count]-2]; [theHelp appendFormat:@"<li><a title='%@ “%@”' href='%@' class='internallink'>%@</a></li>", NSLocalizedString(@"Show MySQL help for", @"show mysql help for"), topic, topic, topic]; } @@ -4008,7 +4007,7 @@ value = [prefs objectForKey:SPNullValue]; } - if ([value isKindOfClass:[MCPGeometryData class]]) { + if ([value isKindOfClass:[SPMySQLGeometryData class]]) { value = [value wktString]; } |