aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/SPMySQLFramework
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2013-03-11 23:03:28 +0000
committerrowanbeentje <rowan@beent.je>2013-03-11 23:03:28 +0000
commitf4967d21057a1363cacc9607b5ace0149a45ca11 (patch)
tree987e9786303429596420858cec43702f5957790b /Frameworks/SPMySQLFramework
parente88ea3b18a1e9bd1f1e5bef51d982992ce211933 (diff)
downloadsequelpro-f4967d21057a1363cacc9607b5ace0149a45ca11.tar.gz
sequelpro-f4967d21057a1363cacc9607b5ace0149a45ca11.tar.bz2
sequelpro-f4967d21057a1363cacc9607b5ace0149a45ca11.zip
- Add a new SPMySQLEmptyResult class to SPMySQLFrameowkr, returning it instead of nil if a query produces no result set. This allows per-result-set properties to be preserved, fixing issues where information like query execution time was lost - addressing Issue #1577
Diffstat (limited to 'Frameworks/SPMySQLFramework')
-rw-r--r--Frameworks/SPMySQLFramework/SPMySQLEmptyResult.h35
-rw-r--r--Frameworks/SPMySQLFramework/SPMySQLEmptyResult.m115
-rw-r--r--Frameworks/SPMySQLFramework/SPMySQLFramework.xcodeproj/project.pbxproj8
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQL.h1
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m56
-rw-r--r--Frameworks/SPMySQLFramework/Source/SPMySQLResult.m39
6 files changed, 215 insertions, 39 deletions
diff --git a/Frameworks/SPMySQLFramework/SPMySQLEmptyResult.h b/Frameworks/SPMySQLFramework/SPMySQLEmptyResult.h
new file mode 100644
index 00000000..153d5d68
--- /dev/null
+++ b/Frameworks/SPMySQLFramework/SPMySQLEmptyResult.h
@@ -0,0 +1,35 @@
+//
+// $Id$
+//
+// SPMySQLEmptyResult.h
+// SPMySQLFramework
+//
+// Created by Rowan Beentje (rowan.beent.je) on March 11, 2013
+// Copyright (c) 2013 Rowan Beentje. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+
+@interface SPMySQLEmptyResult : SPMySQLResult
+
+@end
diff --git a/Frameworks/SPMySQLFramework/SPMySQLEmptyResult.m b/Frameworks/SPMySQLFramework/SPMySQLEmptyResult.m
new file mode 100644
index 00000000..f8f7e268
--- /dev/null
+++ b/Frameworks/SPMySQLFramework/SPMySQLEmptyResult.m
@@ -0,0 +1,115 @@
+//
+// $$
+//
+// SPMySQLEmptyResult.m
+// SPMySQLFramework
+//
+// Created by Rowan Beentje (rowan.beent.je) on March 11, 2013
+// Copyright (c) 2013 Rowan Beentje. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// More info at <http://code.google.com/p/sequel-pro/>
+
+#import "SPMySQLEmptyResult.h"
+
+@implementation SPMySQLEmptyResult
+
+#pragma mark -
+#pragma mark Setup and teardown
+
+/**
+ * Override the standard SPMySQLResult interface
+ */
+- (id)initWithMySQLResult:(void *)theResult stringEncoding:(NSStringEncoding)theStringEncoding
+{
+ return [super init];
+}
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Overrides
+
+- (NSUInteger)numberOfFields
+{
+ return 0;
+}
+
+- (unsigned long long)numberOfRows
+{
+ return 0;
+}
+
+- (NSArray *)fieldNames
+{
+ return nil;
+}
+
+- (void)seekToRow:(unsigned long long)targetRow
+{
+}
+
+- (id)getRow
+{
+ return nil;
+}
+
+- (NSArray *)getRowAsArray
+{
+ return nil;
+}
+
+- (NSDictionary *)getRowAsDictionary
+{
+ return nil;
+}
+
+- (id)getRowAsType:(SPMySQLResultRowType)theType
+{
+ return nil;
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len
+{
+ return 0;
+}
+
+- (NSArray *)fieldDefinitions
+{
+ return nil;
+}
+
+- (id)_stringWithBytes:(const void *)bytes length:(NSUInteger)length
+{
+ return nil;
+}
+
+- (id)_getObjectFromBytes:(char *)bytes ofLength:(NSUInteger)length fieldType:(unsigned int)fieldType fieldDefinitionIndex:(NSUInteger)fieldIndex
+{
+ return nil;
+}
+
+@end
diff --git a/Frameworks/SPMySQLFramework/SPMySQLFramework.xcodeproj/project.pbxproj b/Frameworks/SPMySQLFramework/SPMySQLFramework.xcodeproj/project.pbxproj
index c34ab9d2..1644f7d5 100644
--- a/Frameworks/SPMySQLFramework/SPMySQLFramework.xcodeproj/project.pbxproj
+++ b/Frameworks/SPMySQLFramework/SPMySQLFramework.xcodeproj/project.pbxproj
@@ -62,6 +62,8 @@
58C7C1E514DB6E4C00436315 /* SPMySQLFastStreamingResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C7C1E314DB6E4C00436315 /* SPMySQLFastStreamingResult.m */; };
58C7C1E814DB6E8600436315 /* Field Definitions.h in Headers */ = {isa = PBXBuildFile; fileRef = 58C7C1E614DB6E8600436315 /* Field Definitions.h */; settings = {ATTRIBUTES = (Public, ); }; };
58C7C1E914DB6E8600436315 /* Field Definitions.m in Sources */ = {isa = PBXBuildFile; fileRef = 58C7C1E714DB6E8600436315 /* Field Definitions.m */; };
+ 58D2A4D116EDF1C6002EB401 /* SPMySQLEmptyResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 58D2A4CF16EDF1C6002EB401 /* SPMySQLEmptyResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 58D2A4D216EDF1C6002EB401 /* SPMySQLEmptyResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D2A4D016EDF1C6002EB401 /* SPMySQLEmptyResult.m */; };
8DC2EF530486A6940098B216 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C1666FE841158C02AAC07 /* InfoPlist.strings */; };
8DC2EF570486A6940098B216 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */
@@ -129,6 +131,8 @@
58C7C1E314DB6E4C00436315 /* SPMySQLFastStreamingResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SPMySQLFastStreamingResult.m; path = Source/SPMySQLFastStreamingResult.m; sourceTree = "<group>"; };
58C7C1E614DB6E8600436315 /* Field Definitions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Field Definitions.h"; path = "Source/SPMySQLResult Categories/Field Definitions.h"; sourceTree = "<group>"; };
58C7C1E714DB6E8600436315 /* Field Definitions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "Field Definitions.m"; path = "Source/SPMySQLResult Categories/Field Definitions.m"; sourceTree = "<group>"; };
+ 58D2A4CF16EDF1C6002EB401 /* SPMySQLEmptyResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPMySQLEmptyResult.h; sourceTree = "<group>"; };
+ 58D2A4D016EDF1C6002EB401 /* SPMySQLEmptyResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPMySQLEmptyResult.m; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* SPMySQL.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SPMySQL.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
@@ -202,6 +206,8 @@
584294EB14CB8002000F8438 /* Connection Categories */,
5884165314D2306A0078027F /* SPMySQLResult.h */,
5884165414D2306A0078027F /* SPMySQLResult.m */,
+ 58D2A4CF16EDF1C6002EB401 /* SPMySQLEmptyResult.h */,
+ 58D2A4D016EDF1C6002EB401 /* SPMySQLEmptyResult.m */,
586A99F914F02E21007F82BF /* SPMySQLStreamingResult.h */,
586A99FA14F02E21007F82BF /* SPMySQLStreamingResult.m */,
58C7C1E214DB6E4C00436315 /* SPMySQLFastStreamingResult.h */,
@@ -397,6 +403,7 @@
586AA81414F6C648007F82BF /* SPMySQLArrayAdditions.h in Headers */,
584D812E15057ECD00F24774 /* SPMySQLKeepAliveTimer.h in Headers */,
584D82551509775000F24774 /* Copying.h in Headers */,
+ 58D2A4D116EDF1C6002EB401 /* SPMySQLEmptyResult.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -485,6 +492,7 @@
586AA16814F30C5F007F82BF /* Convenience Methods.m in Sources */,
584D812F15057ECD00F24774 /* SPMySQLKeepAliveTimer.m in Sources */,
584D82561509775000F24774 /* Copying.m in Sources */,
+ 58D2A4D216EDF1C6002EB401 /* SPMySQLEmptyResult.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQL.h b/Frameworks/SPMySQLFramework/Source/SPMySQL.h
index aa9008b6..904f390c 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQL.h
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQL.h
@@ -58,6 +58,7 @@
// MySQL result set, streaming subclasses of same, and associated categories
#import "SPMySQLResult.h"
+#import "SPMySQLEmptyResult.h"
#import "SPMySQLStreamingResult.h"
#import "SPMySQLFastStreamingResult.h"
#import "Field Definitions.h"
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m
index 22e35648..c007a07e 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLConnection Categories/Querying & Preparation.m
@@ -322,34 +322,38 @@
id theResult = nil;
// On success, if there is a query result, retrieve the result data type
- if (!queryStatus && mysql_field_count(mySQLConnection)) {
- MYSQL_RES *mysqlResult;
-
- switch (theReturnType) {
-
- // For standard result sets, retrieve all the results now, and afterwards
- // update the affected row count.
- case SPMySQLResultAsResult:
- mysqlResult = mysql_store_result(mySQLConnection);
- theResult = [[SPMySQLResult alloc] initWithMySQLResult:mysqlResult stringEncoding:theEncoding];
- theAffectedRowCount = mysql_affected_rows(mySQLConnection);
- break;
-
- // For fast streaming and low memory streaming result sets, set up the result
- case SPMySQLResultAsLowMemStreamingResult:
- mysqlResult = mysql_use_result(mySQLConnection);
- theResult = [[SPMySQLStreamingResult alloc] initWithMySQLResult:mysqlResult stringEncoding:theEncoding connection:self];
- break;
+ if (!queryStatus) {
+ if (mysql_field_count(mySQLConnection)) {
+ MYSQL_RES *mysqlResult;
+
+ switch (theReturnType) {
+
+ // For standard result sets, retrieve all the results now, and afterwards
+ // update the affected row count.
+ case SPMySQLResultAsResult:
+ mysqlResult = mysql_store_result(mySQLConnection);
+ theResult = [[SPMySQLResult alloc] initWithMySQLResult:mysqlResult stringEncoding:theEncoding];
+ theAffectedRowCount = mysql_affected_rows(mySQLConnection);
+ break;
+
+ // For fast streaming and low memory streaming result sets, set up the result
+ case SPMySQLResultAsLowMemStreamingResult:
+ mysqlResult = mysql_use_result(mySQLConnection);
+ theResult = [[SPMySQLStreamingResult alloc] initWithMySQLResult:mysqlResult stringEncoding:theEncoding connection:self];
+ break;
+
+ case SPMySQLResultAsFastStreamingResult:
+ mysqlResult = mysql_use_result(mySQLConnection);
+ theResult = [[SPMySQLFastStreamingResult alloc] initWithMySQLResult:mysqlResult stringEncoding:theEncoding connection:self];
+ break;
+ }
- case SPMySQLResultAsFastStreamingResult:
- mysqlResult = mysql_use_result(mySQLConnection);
- theResult = [[SPMySQLFastStreamingResult alloc] initWithMySQLResult:mysqlResult stringEncoding:theEncoding connection:self];
- break;
+ // Update the error message, if appropriate, to reflect result store errors or overall success
+ theErrorMessage = [self _stringForCString:mysql_error(mySQLConnection)];
+ theErrorID = mysql_errno(mySQLConnection);
+ } else {
+ theResult = [[SPMySQLEmptyResult alloc] init];
}
-
- // Update the error message, if appropriate, to reflect result store errors or overall success
- theErrorMessage = [self _stringForCString:mysql_error(mySQLConnection)];
- theErrorID = mysql_errno(mySQLConnection);
}
// Update the connection's stored insert ID if available
diff --git a/Frameworks/SPMySQLFramework/Source/SPMySQLResult.m b/Frameworks/SPMySQLFramework/Source/SPMySQLResult.m
index 3ccd5727..ee758bad 100644
--- a/Frameworks/SPMySQLFramework/Source/SPMySQLResult.m
+++ b/Frameworks/SPMySQLFramework/Source/SPMySQLResult.m
@@ -90,12 +90,27 @@ static id NSNullPointer;
}
/**
- * Prevent SPMySQLResults from being init'd normally.
+ * Standard initialisation - not intended for external use.
*/
- (id)init
{
- [NSException raise:NSInternalInconsistencyException format:@"SPMySQLResults should not be init'd directly; use initWithMySQLResult:stringEncoding: instead."];
- return nil;
+ if ((self = [super init])) {
+ stringEncoding = NSASCIIStringEncoding;
+ queryExecutionTime = -1;
+
+ resultSet = NULL;
+ numberOfFields = 0;
+ numberOfRows = 0;
+ currentRowIndex = 0;
+
+ fieldDefinitions = NULL;
+ fieldNames = NULL;
+ fieldTypes = NULL;
+
+ defaultRowReturnType = SPMySQLResultRowAsDictionary;
+ }
+
+ return self;
}
/**
@@ -108,15 +123,13 @@ static id NSNullPointer;
// If no result set was passed in, return nil.
if (!theResult) return nil;
- if ((self = [super init])) {
+ if ((self = [self init])) {
stringEncoding = theStringEncoding;
- queryExecutionTime = -1;
// Get the result set and cache the number of fields and number of rows
resultSet = theResult;
numberOfFields = mysql_num_fields(resultSet);
numberOfRows = mysql_num_rows(resultSet);
- currentRowIndex = 0;
// Cache the field definitions and build up an array of cached field names and types
fieldDefinitions = mysql_fetch_fields(resultSet);
@@ -127,8 +140,6 @@ static id NSNullPointer;
fieldNames[i] = [[self _stringWithBytes:aField.name length:aField.name_length] retain];
fieldTypes[i] = aField.type;
}
-
- defaultRowReturnType = SPMySQLResultRowAsDictionary;
}
return self;
@@ -136,13 +147,15 @@ static id NSNullPointer;
- (void)dealloc
{
- mysql_free_result(resultSet);
+ if (resultSet) {
+ mysql_free_result(resultSet);
- for (NSUInteger i = 0; i < numberOfFields; i++) {
- [fieldNames[i] release];
+ for (NSUInteger i = 0; i < numberOfFields; i++) {
+ [fieldNames[i] release];
+ }
+ free(fieldNames);
+ free(fieldTypes);
}
- free(fieldNames);
- free(fieldTypes);
[super dealloc];
}