Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ccgus/fmdb.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert M. Ryan <robert.ryan@mindspring.com>2015-10-30 06:22:06 +0300
committerRobert M. Ryan <robert.ryan@mindspring.com>2015-10-30 06:22:06 +0300
commitd2e1b514127547d7c5a62c5aeb25dd24b18e9501 (patch)
tree9d4892734d88d75c6b4e3134dec1403fb93bf62b
parentb6f7a7d9314f5a3f7df28eb3061ecc3c33559cc7 (diff)
Add renditions of executeQuery and executeUpdate that throw errors in Swift
These renditions are `executeQuery:values:error:` and `executeUpdate:values:error:`. Updated README, which has Swift 2 example, accordingly.
-rw-r--r--CHANGES_AND_TODO_LIST.txt3
-rw-r--r--README.markdown23
-rw-r--r--Tests/Tests-Info.plist2
-rw-r--r--fmdb.xcodeproj/project.pbxproj15
-rw-r--r--fmdb.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme13
-rw-r--r--src/fmdb/FMDatabase.h67
-rw-r--r--src/fmdb/FMDatabase.m12
7 files changed, 105 insertions, 30 deletions
diff --git a/CHANGES_AND_TODO_LIST.txt b/CHANGES_AND_TODO_LIST.txt
index 44db745..c6a375d 100644
--- a/CHANGES_AND_TODO_LIST.txt
+++ b/CHANGES_AND_TODO_LIST.txt
@@ -3,6 +3,9 @@ Zip, nada, zilch. Got any ideas?
If you would like to contribute some code- awesome! I just ask that you make it conform to the coding conventions already set in here, and to add a couple of tests for your new code to fmdb.m. And of course, the code should be of general use to more than just a couple of folks. Send your patches to gus@flyingmeat.com.
+2015.10.29
+ Added renditions of `executeUpdate:values:error:` and `executeQuery:values:error:`, which in Swift 2 throw errors.
+
2015.01.23
Added Swift renditions of the variadic methods of FMDatabaseAdditions.
diff --git a/README.markdown b/README.markdown
index 934579d..1ec0778 100644
--- a/README.markdown
+++ b/README.markdown
@@ -278,7 +278,7 @@ To do this, you must:
#import "FMDB.h"
```
-4. Optionally, copy the `FMDatabaseVariadic.swift` from the "src/extra/Swift Extensions" folder into your project. This allows you to use `executeUpdate` and `executeQuery` with variadic parameters, rather than the `withArgumentsInArray` rendition.
+4. Use the variations of `executeQuery` and `executeUpdate` with the `sql` and `values` parameters with `try` pattern, as shown below. These renditions of `executeQuery` and `executeUpdate` both `throw` errors in true Swift 2 fashion.
If you do the above, you can then write Swift code that uses FMDatabase. For example:
@@ -293,27 +293,20 @@ if !database.open() {
return
}
-if !database.executeUpdate("create table test(x text, y text, z text)", withArgumentsInArray: nil) {
- print("create table failed: \(database.lastErrorMessage())")
-}
-
-if !database.executeUpdate("insert into test (x, y, z) values (?, ?, ?)", withArgumentsInArray: ["a", "b", "c"]) {
- print("insert 1 table failed: \(database.lastErrorMessage())")
-}
-
-if !database.executeUpdate("insert into test (x, y, z) values (?, ?, ?)", withArgumentsInArray: ["e", "f", "g"]) {
- print("insert 2 table failed: \(database.lastErrorMessage())")
-}
+do {
+ try database.executeUpdate("create table test(x text, y text, z text)", values: nil)
+ try database.executeUpdate("insert into test (x, y, z) values (?, ?, ?)", values: ["a", "b", "c"])
+ try database.executeUpdate("insert into test (x, y, z) values (?, ?, ?)", values: ["e", "f", "g"])
-if let rs = database.executeQuery("select x, y, z from test", withArgumentsInArray: nil) {
+ let rs = try database.executeQuery("select x, y, z from test", values: nil)
while rs.next() {
let x = rs.stringForColumn("x")
let y = rs.stringForColumn("y")
let z = rs.stringForColumn("z")
print("x = \(x); y = \(y); z = \(z)")
}
-} else {
- print("select failed: \(database.lastErrorMessage())")
+} catch let error as NSError {
+ print("failed: \(error.localizedDescription)")
}
database.close()
diff --git a/Tests/Tests-Info.plist b/Tests/Tests-Info.plist
index 30e7ee2..169b6f7 100644
--- a/Tests/Tests-Info.plist
+++ b/Tests/Tests-Info.plist
@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
- <string>me.grahamdennis.${PRODUCT_NAME:rfc1034identifier}</string>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
diff --git a/fmdb.xcodeproj/project.pbxproj b/fmdb.xcodeproj/project.pbxproj
index 37772d8..89d0700 100644
--- a/fmdb.xcodeproj/project.pbxproj
+++ b/fmdb.xcodeproj/project.pbxproj
@@ -436,7 +436,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0610;
+ LastUpgradeCheck = 0710;
TargetAttributes = {
BF5D041518416BB2008C5AA9 = {
TestTargetID = EE4290EE12B42F870088BD94;
@@ -608,7 +608,9 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_NO_COMMON_BLOCKS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
@@ -620,7 +622,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
- SDKROOT = macosx10.9;
+ SDKROOT = macosx;
};
name = Debug;
};
@@ -636,13 +638,14 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_NO_COMMON_BLOCKS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- SDKROOT = macosx10.9;
+ SDKROOT = macosx;
};
name = Release;
};
@@ -737,8 +740,9 @@
INFOPLIST_FILE = "Tests/Tests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8;
ONLY_ACTIVE_ARCH = YES;
+ PRODUCT_BUNDLE_IDENTIFIER = "me.grahamdennis.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx10.9;
+ SDKROOT = macosx;
WRAPPER_EXTENSION = xctest;
};
name = Debug;
@@ -772,8 +776,9 @@
GCC_WARN_UNUSED_FUNCTION = YES;
INFOPLIST_FILE = "Tests/Tests-Info.plist";
MACOSX_DEPLOYMENT_TARGET = 10.8;
+ PRODUCT_BUNDLE_IDENTIFIER = "me.grahamdennis.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx10.9;
+ SDKROOT = macosx;
WRAPPER_EXTENSION = xctest;
};
name = Release;
diff --git a/fmdb.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme b/fmdb.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme
index 23ed8cf..754abff 100644
--- a/fmdb.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme
+++ b/fmdb.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
- LastUpgradeVersion = "0630"
+ LastUpgradeVersion = "0710"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -23,10 +23,10 @@
</BuildActionEntries>
</BuildAction>
<TestAction
+ buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES"
- buildConfiguration = "Debug">
+ shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
@@ -48,15 +48,18 @@
ReferencedContainer = "container:fmdb.xcodeproj">
</BuildableReference>
</MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
</TestAction>
<LaunchAction
+ buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
@@ -71,10 +74,10 @@
</AdditionalOptions>
</LaunchAction>
<ProfileAction
+ buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
- buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
diff --git a/src/fmdb/FMDatabase.h b/src/fmdb/FMDatabase.h
index 1aec77d..213d222 100644
--- a/src/fmdb/FMDatabase.h
+++ b/src/fmdb/FMDatabase.h
@@ -336,23 +336,52 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
- (BOOL)executeUpdateWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);
/** Execute single update statement
-
+
This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters.
+
+ The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method.
+
+ @param sql The SQL to be performed, with optional `?` placeholders.
+
+ @param arguments A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement.
+
+ @return `YES` upon success; `NO` upon failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
+
+ @see executeUpdate:values:error:
+ @see lastError
+ @see lastErrorCode
+ @see lastErrorMessage
+ */
+
+- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;
+/** Execute single update statement
+
+ This method executes a single SQL update statement (i.e. any SQL that does not return results, such as `UPDATE`, `INSERT`, or `DELETE`. This method employs [`sqlite3_prepare_v2`](http://sqlite.org/c3ref/prepare.html) and [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) binding any `?` placeholders in the SQL with the optional list of parameters.
+
The optional values provided to this method should be objects (e.g. `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects), not fundamental data types (e.g. `int`, `long`, `NSInteger`, etc.). This method automatically handles the aforementioned object types, and all other object types will be interpreted as text values using the object's `description` method.
+
+ This is similar to `<executeUpdate:withArgumentsInArray:>`, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned.
+ In Swift 2, this throws errors, as if it were defined as follows:
+
+ `func executeUpdate(sql: String!, values: [AnyObject]!) throws -> Bool`
+
@param sql The SQL to be performed, with optional `?` placeholders.
+
+ @param values A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement.
- @param arguments A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement.
+ @param error A `NSError` object to receive any error object (if any).
@return `YES` upon success; `NO` upon failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
-
+
@see lastError
@see lastErrorCode
@see lastErrorMessage
+
*/
-- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;
+- (BOOL)executeUpdate:(NSString*)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error;
/** Execute single update statement
@@ -524,6 +553,7 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
@return A `<FMResultSet>` for the result set upon success; `nil` upon failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
+ @see -executeQuery:values:error:
@see FMResultSet
@see [`FMResultSet next`](<[FMResultSet next]>)
*/
@@ -531,6 +561,35 @@ typedef int(^FMDBExecuteStatementsCallbackBlock)(NSDictionary *resultsDictionary
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments;
/** Execute select statement
+
+ Executing queries returns an `<FMResultSet>` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `<lastErrorMessage>` and `<lastErrorMessage>` methods to determine why a query failed.
+
+ In order to iterate through the results of your query, you use a `while()` loop. You also need to "step" (via `<[FMResultSet next]>`) from one record to the other.
+
+ This is similar to `<executeQuery:withArgumentsInArray:>`, except that this also accepts a pointer to a `NSError` pointer, so that errors can be returned.
+
+ In Swift 2, this throws errors, as if it were defined as follows:
+
+ `func executeQuery(sql: String!, values: [AnyObject]!) throws -> FMResultSet!`
+
+ @param sql The SELECT statement to be performed, with optional `?` placeholders.
+
+ @param values A `NSArray` of objects to be used when binding values to the `?` placeholders in the SQL statement.
+
+ @param error A `NSError` object to receive any error object (if any).
+
+ @return A `<FMResultSet>` for the result set upon success; `nil` upon failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
+
+ @see FMResultSet
+ @see [`FMResultSet next`](<[FMResultSet next]>)
+
+ @note When called from Swift, only use the first two parameters, `sql` and `values`. This but throws the error.
+
+ */
+
+- (FMResultSet *)executeQuery:(NSString *)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error;
+
+/** Execute select statement
Executing queries returns an `<FMResultSet>` object if successful, and `nil` upon failure. Like executing updates, there is a variant that accepts an `NSError **` parameter. Otherwise you should use the `<lastErrorMessage>` and `<lastErrorMessage>` methods to determine why a query failed.
diff --git a/src/fmdb/FMDatabase.m b/src/fmdb/FMDatabase.m
index 40e3b06..e9757a6 100644
--- a/src/fmdb/FMDatabase.m
+++ b/src/fmdb/FMDatabase.m
@@ -907,6 +907,14 @@ static int FMDBDatabaseBusyHandler(void *f, int count) {
return [self executeQuery:sql withArgumentsInArray:arguments orDictionary:nil orVAList:nil];
}
+- (FMResultSet *)executeQuery:(NSString *)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error {
+ FMResultSet *rs = [self executeQuery:sql withArgumentsInArray:values orDictionary:nil orVAList:nil];
+ if (!rs && error) {
+ *error = [self lastError];
+ }
+ return rs;
+}
+
- (FMResultSet *)executeQuery:(NSString*)sql withVAList:(va_list)args {
return [self executeQuery:sql withArgumentsInArray:nil orDictionary:nil orVAList:args];
}
@@ -1119,6 +1127,10 @@ static int FMDBDatabaseBusyHandler(void *f, int count) {
return [self executeUpdate:sql error:nil withArgumentsInArray:arguments orDictionary:nil orVAList:nil];
}
+- (BOOL)executeUpdate:(NSString*)sql values:(NSArray *)values error:(NSError * __autoreleasing *)error {
+ return [self executeUpdate:sql error:error withArgumentsInArray:values orDictionary:nil orVAList:nil];
+}
+
- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)arguments {
return [self executeUpdate:sql error:nil withArgumentsInArray:nil orDictionary:arguments orVAList:nil];
}