Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
* More formatting changes
* Fix an unintended switch/case fallthrough (the error got caught soon afterwards, so this never really caused problems)
* Fix a typo in the mysql fallback charset mappings (119 should’ve been 199)
* Fix a charset confusion issue (SPMySQL’s compiled-in C strings are in UTF-8, not the connection encoding of the mysql connection)
  • Loading branch information
dmoagx committed May 1, 2018
1 parent 5bd7cde commit 7f35608
Show file tree
Hide file tree
Showing 23 changed files with 260 additions and 327 deletions.
@@ -1,5 +1,5 @@
//
// Encoding.m
// Conversion.h
// SPMySQLFramework
//
// Created by Rowan Beentje (rowan.beent.je) on January 22, 2012
Expand Down
@@ -1,5 +1,5 @@
//
// Encoding.m
// Conversion.m
// SPMySQLFramework
//
// Created by Rowan Beentje (rowan.beent.je) on January 22, 2012
Expand Down Expand Up @@ -47,7 +47,6 @@ @implementation SPMySQLConnection (Conversion)
But the "string" can already contain NUL bytes, so it's not a valid c string anyway.
+ (const char *)_cStringForString:(NSString *)aString usingEncoding:(NSStringEncoding)anEncoding returningLengthAs:(NSUInteger *)cStringLengthPointer
{
// Don't try and convert nil strings
if (!aString) return NULL;

Expand All @@ -73,7 +72,6 @@ + (const char *)_cStringForString:(NSString *)aString usingEncoding:(NSStringEnc
*/
- (const char *)_cStringForString:(NSString *)aString
{

// Use a cached reference to avoid dynamic method overhead
return _cStringForStringWithEncoding(aString, stringEncoding, NULL);
}
Expand Down
Expand Up @@ -45,7 +45,6 @@ @implementation SPMySQLConnection (Databases_and_Tables)
*/
- (BOOL)selectDatabase:(NSString *)aDatabase
{

// If no database was supplied, can't deselected - return NO.
if (!aDatabase) return NO;

Expand Down Expand Up @@ -96,7 +95,6 @@ - (BOOL)selectDatabase:(NSString *)aDatabase
*/
- (NSArray *)databases
{

// Wrap the related databasesLike: function to avoid code duplication
return [self databasesLike:nil];
}
Expand Down Expand Up @@ -151,7 +149,6 @@ - (NSArray *)databasesLike:(NSString *)nameLikeString
*/
- (NSArray *)tables
{

// Wrap the related tablesLike:fromDatabase: function to avoid code duplication
return [self tablesLike:nil fromDatabase:nil];
}
Expand All @@ -166,10 +163,8 @@ - (NSArray *)tables
*/
- (NSArray *)tablesLike:(NSString *)nameLikeString
{

// Wrap the related tablesLike:fromDatabase: function to avoid code duplication
return [self tablesLike:nameLikeString fromDatabase:nil];

}

/**
Expand All @@ -180,10 +175,8 @@ - (NSArray *)tablesLike:(NSString *)nameLikeString
*/
- (NSArray *)tablesFromDatabase:(NSString *)aDatabase
{

// Wrap the related tablesLike:fromDatabase: function to avoid code duplication
return [self tablesLike:nil fromDatabase:aDatabase];

}

/**
Expand Down Expand Up @@ -246,7 +239,6 @@ @implementation SPMySQLConnection (Databases_and_Tables_Private_API)
*/
- (BOOL)_storeAndAlterEncodingToUTF8IfRequired
{

// If the encoding is already UTF8, no change is required.
if ([encoding isEqualToString:@"utf8"] && !encodingUsesLatin1Transport) return NO;

Expand Down
Expand Up @@ -82,7 +82,6 @@ - (BOOL)encodingUsesLatin1Transport
*/
- (BOOL)setEncoding:(NSString *)theEncoding
{

// MySQL versions prior to 4.1 don't support encoding changes; return NO on those
// versions.
if (![self serverVersionIsGreaterThanOrEqualTo:4 minorVersion:1 releaseVersion:0]) {
Expand Down Expand Up @@ -116,14 +115,13 @@ - (BOOL)setEncoding:(NSString *)theEncoding
* Latin1 transport is a compatibility mode in place for compatibility with older
* incorrect setups, where databases and clients might both be set to use UTF8 (or
* other encodings) for storing and retrieving data, but the MySQL link was never
* set to UTF8 mode; as a result, multibyte characters where split by the connection
* set to UTF8 mode; as a result, multibyte characters were split by the connection
* into pairs of characters, resulting in malformed storage. The data works
* correctly if written and read in the same way, so this mode allows correct display
* of that data.
*/
- (BOOL)setEncodingUsesLatin1Transport:(BOOL)useLatin1
{

// MySQL versions prior to 4.1 don't support encoding changes; return NO on those
// versions.
if (![self serverVersionIsGreaterThanOrEqualTo:4 minorVersion:1 releaseVersion:0]) {
Expand Down Expand Up @@ -208,7 +206,6 @@ - (void)restoreStoredEncoding
*/
+ (NSStringEncoding)stringEncodingForMySQLCharset:(const char *)mysqlCharset
{

// Handle the most common cases first
if (!strcmp(mysqlCharset, "utf8")) {
return NSUTF8StringEncoding;
Expand Down Expand Up @@ -337,7 +334,6 @@ + (NSStringEncoding)stringEncodingForMySQLCharset:(const char *)mysqlCharset
*/
+ (NSString *)mySQLCharsetForStringEncoding:(NSStringEncoding)aStringEncoding
{

// Switch through the list of NSStringEncodings from NSString, returning the most
// appropriate encoding for each
switch (aStringEncoding) {
Expand Down
Expand Up @@ -42,12 +42,11 @@ @implementation SPMySQLConnection (Locking)
*/
- (void)_lockConnection
{

// We can only start a query when the condition is SPMySQLConnectionIdle
// We can only start a query when the condition is SPMySQLConnectionIdle
[connectionLock lockWhenCondition:SPMySQLConnectionIdle];
// Set the condition to SPMySQLConnectionBusy
[connectionLock unlockWithCondition:SPMySQLConnectionBusy];

// Set the condition to SPMySQLConnectionBusy
[connectionLock unlockWithCondition:SPMySQLConnectionBusy];
}

/**
Expand All @@ -58,7 +57,6 @@ - (void)_lockConnection
*/
- (BOOL)_tryLockConnection
{

// If the connection is already is use, return failure
if (![connectionLock tryLockWhenCondition:SPMySQLConnectionIdle]) {
return NO;
Expand All @@ -75,28 +73,31 @@ - (BOOL)_tryLockConnection
*/
- (void)_unlockConnection
{
// Always lock the conditional lock before proceeding
[connectionLock lock];

// Check if the connection actually was busy. If it wasn't busy,
// it means the connection may have been unlocked twice. This is
// potentially dangerous, so we log this to the console
if ([connectionLock condition] != SPMySQLConnectionBusy) {
NSLog(@"SPMySQLConnection: Tried to unlock the connection, but it wasn't locked.");
}

// Since we connected with CLIENT_MULTI_RESULT, we must make sure there are not more results!
// This is still a bit of a dirty hack
if (
state == SPMySQLConnected &&
mySQLConnection &&
mySQLConnection->net.vio &&
mySQLConnection->net.buff &&
mysql_more_results(mySQLConnection)
) {
NSLog(@"SPMySQLConnection: Discarding unretrieved results. This is currently normal when using CALL.");
[self _flushMultipleResultSets];
}

// Always lock the conditional lock before proceeding
[connectionLock lock];

// Check if the connection actually was busy. If it wasn't busy,
// it means the connection may have been unlocked twice. This is
// potentially dangerous, so we log this to the console
if ([connectionLock condition] != SPMySQLConnectionBusy) {
NSLog(@"SPMySQLConnection: Tried to unlock the connection, but it wasn't locked.");
}

// Since we connected with CLIENT_MULTI_RESULT, we must make sure there are not more results!
// This is still a bit of a dirty hack
if (state == SPMySQLConnected
&& mySQLConnection && mySQLConnection->net.vio && mySQLConnection->net.buff && mysql_more_results(mySQLConnection))
{
NSLog(@"SPMySQLConnection: Discarding unretrieved results. This is currently normal when using CALL.");
[self _flushMultipleResultSets];
}

// Tell everyone that the connection is available again
[connectionLock unlockWithCondition:SPMySQLConnectionIdle];
// Tell everyone that the connection is available again
[connectionLock unlockWithCondition:SPMySQLConnectionIdle];
}

@end
Expand Up @@ -67,7 +67,6 @@ - (BOOL)isMaxQuerySizeEditable
*/
- (NSUInteger)setGlobalMaxQuerySize:(NSUInteger)newMaxSize
{

// Perform basic validation. First, ensure the max query size is editable
if (![self isMaxQuerySizeEditable]) return NSNotFound;

Expand Down Expand Up @@ -114,8 +113,7 @@ - (NSInteger)_queryMaxAllowedPacketWithSQL:(NSString *)query resultInColumn:(NSU

NSInteger _maxQuerySize = maxQuerySizeString ? [maxQuerySizeString integerValue] : 0;

if(_maxQuerySize == 0)
NSLog(@"Query (%@) for max_allowed_packet returned invalid value: %ld (raw value: %@) (on %@)", query, _maxQuerySize, maxQuerySizeString, [self serverVersionString]);
if(_maxQuerySize == 0) NSLog(@"Query (%@) for max_allowed_packet returned invalid value: %ld (raw value: %@) (on %@)", query, _maxQuerySize, maxQuerySizeString, [self serverVersionString]);

return _maxQuerySize;
}
Expand Down Expand Up @@ -164,12 +162,10 @@ - (void)_updateMaxQuerySizeEditability
*/
- (BOOL)_attemptMaxQuerySizeIncreaseTo:(NSUInteger)targetSize
{

// If the query size is editable, attempt to increase the size
if ([self isMaxQuerySizeEditable]) {
NSUInteger newSize = [self setGlobalMaxQuerySize:targetSize];
if (newSize != NSNotFound) {

// Successfully increased the global size - reconnect to use it, and return success
[self _reconnectAllowingRetries:YES];
return YES;
Expand All @@ -185,6 +181,7 @@ - (BOOL)_attemptMaxQuerySizeIncreaseTo:(NSUInteger)targetSize
[delegate queryGaveError:errorMessage connection:self];
}

//TODO Setting the last error above should be enough at the framework level. Also this is the only case where -showErrorWithTitle:message: is even used, so we should get rid of it.
// Display an alert as this is a special failure
if ([delegate respondsToSelector:@selector(showErrorWithTitle:message:)]) {
[delegate showErrorWithTitle:NSLocalizedString(@"Error", @"error") message:errorMessage];
Expand All @@ -202,7 +199,6 @@ - (BOOL)_attemptMaxQuerySizeIncreaseTo:(NSUInteger)targetSize
*/
- (void)_restoreMaximumQuerySizeAfterQuery
{

// Return if no action needs to be performed
if (queryActionShouldRestoreMaxQuerySize == NSNotFound) return;

Expand Down
Expand Up @@ -30,13 +30,6 @@

// This class is private to the framework.

typedef struct {
MYSQL *mySQLConnection;
volatile BOOL *keepAlivePingThreadActivePointer;
volatile BOOL *keepAliveLastPingSuccessPointer;
void *parentId;
} SPMySQLConnectionPingDetails;

@interface SPMySQLConnection (Ping_and_KeepAlive)

// Keepalive ping initialisation
Expand Down
Expand Up @@ -35,6 +35,13 @@
#import <pthread.h>
#include <stdio.h>

typedef struct {
MYSQL *mySQLConnection;
volatile BOOL *keepAlivePingThreadActivePointer;
volatile BOOL *keepAliveLastPingSuccessPointer;
void *parentId;
} SPMySQLConnectionPingDetails;

@implementation SPMySQLConnection (Ping_and_KeepAlive)

#pragma mark -
Expand All @@ -47,7 +54,6 @@ @implementation SPMySQLConnection (Ping_and_KeepAlive)
*/
- (void)_keepAlive
{

// Do nothing if not connected, if keepalive is disabled, or a keepalive is in
// progress.
if (state != SPMySQLConnected || !useKeepAlive) return;
Expand Down Expand Up @@ -185,10 +191,11 @@ - (BOOL)_pingConnectionUsingLoopDelay:(NSUInteger)loopDelay

// If the ping timeout has been exceeded, or the ping thread has been
// cancelled, force a timeout; double-check that the thread is still active.
if (([[NSThread currentThread] isCancelled] || pingElapsedTime > pingTimeout)
if (
([[NSThread currentThread] isCancelled] || pingElapsedTime > pingTimeout)
&& keepAlivePingThreadActive
&& !threadCancelled)
{
&& !threadCancelled
) {
pthread_cancel(keepAlivePingThread_t);
threadCancelled = YES;

Expand All @@ -209,7 +216,7 @@ - (BOOL)_pingConnectionUsingLoopDelay:(NSUInteger)loopDelay
keepAlivePingThread_t = NULL;
pthread_attr_destroy(&attr);

// Unlock the connection
// Unlock the connection
[self _unlockConnection];

return keepAliveLastPingSuccess;
Expand Down Expand Up @@ -278,7 +285,6 @@ void _pingThreadCleanup(void *pingDetails)
*/
- (BOOL)_cancelKeepAlives
{

// If no keepalive thread is active, return
if (keepAliveThread) {

Expand Down
Expand Up @@ -64,7 +64,6 @@ - (NSString *)escapeAndQuoteString:(NSString *)theString
*/
- (NSString *)escapeString:(NSString *)theString includingQuotes:(BOOL)includeQuotes
{

// Return nil strings untouched
if (!theString) return theString;

Expand Down Expand Up @@ -137,7 +136,6 @@ - (NSString *)escapeAndQuoteData:(NSData *)theData
*/
- (NSString *)escapeData:(NSData *)theData includingQuotes:(BOOL)includeQuotes
{

// Return nil datas as nil strings
if (!theData) return nil;

Expand Down Expand Up @@ -345,7 +343,7 @@ - (id)queryString:(NSString *)theQueryString usingEncoding:(NSStringEncoding)the

} while (--queryAttemptsAllowed > 0);

id theResult = nil;
SPMySQLResult *theResult = nil;

// On success, if there is a query result, retrieve the result data type
if (!queryStatus) {
Expand Down Expand Up @@ -549,7 +547,6 @@ + (BOOL)isErrorIDConnectionError:(NSUInteger)theErrorID
*/
- (void)cancelCurrentQuery
{

// If not connected, no action is required
if (state != SPMySQLConnected && state != SPMySQLDisconnecting) return;

Expand Down Expand Up @@ -656,7 +653,6 @@ @implementation SPMySQLConnection (Querying_and_Preparation_Private_API)
*/
- (void)_flushMultipleResultSets
{

// Repeat as long as there are results
while (!mysql_next_result(mySQLConnection)) {
MYSQL_RES *eachResult = mysql_use_result(mySQLConnection);
Expand Down Expand Up @@ -691,7 +687,6 @@ - (void)_updateLastErrorInfos
*/
- (void)_updateLastErrorMessage:(NSString *)theErrorMessage
{

// If an error message wasn't supplied, select one from the connection
if (!theErrorMessage) {
theErrorMessage = [self _stringForCString:mysql_error(mySQLConnection)];
Expand All @@ -714,7 +709,6 @@ - (void)_updateLastErrorMessage:(NSString *)theErrorMessage
*/
- (void)_updateLastErrorID:(NSUInteger)theErrorID
{

// If NSNotFound was supplied as the ID, ask the connection for the last error
if (theErrorID == NSNotFound) {
queryErrorID = mysql_errno(mySQLConnection);
Expand Down
Expand Up @@ -136,7 +136,6 @@ - (SPMySQLResult *)listProcesses
*/
- (BOOL)killQueryOnThreadID:(unsigned long)theThreadID
{

// Note that mysql_kill has been deprecated, so use a query to perform this task.
NSMutableString *killQuery = [NSMutableString stringWithString:@"KILL"];
if ([self serverVersionIsGreaterThanOrEqualTo:5 minorVersion:0 releaseVersion:0]) {
Expand Down

0 comments on commit 7f35608

Please sign in to comment.