Skip to content

Commit

Permalink
Merge branch 'master' of git://github.com/robertmryan/fmdb into rober…
Browse files Browse the repository at this point in the history
…tmryan-master
  • Loading branch information
ccgus committed Apr 23, 2014
2 parents 8941bf1 + b044f2a commit 5cd7302
Show file tree
Hide file tree
Showing 8 changed files with 335 additions and 64 deletions.
4 changes: 2 additions & 2 deletions CHANGES_AND_TODO_LIST.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ If you would like to contribute some code- awesome! I just ask that you make it

- To build that HTML documentation, once you've installed `appledoc`, you issue the command:

appledoc --project-name FMDB --project-company ccgus --explicit-crossref --no-merge-categories --output ../Documentation .
appledoc --project-name FMDB --project-company ccgus --explicit-crossref --no-merge-categories --output ../Documentation --ignore *.m .

- If you want online help integrated right into Xcode, you can issue the command:

appledoc --project-name FMDB --project-company ccgus --explicit-crossref --merge-categories --install-docset --output ../Documentation .
appledoc --project-name FMDB --project-company ccgus --explicit-crossref --merge-categories --install-docset --output --ignore *.m ../Documentation .

2013.05.24
Merged in Chris Wright's date format additions to FMDatabase.
Expand Down
43 changes: 39 additions & 4 deletions Tests/FMDatabaseTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -818,19 +818,54 @@ - (void)testApplicationID
{
uint32_t appID = NSHFSTypeCodeFromFileType(NSFileTypeForHFSTypeCode('fmdb'));

[db setApplicationID:appID];
[self.db setApplicationID:appID];

uint32_t rAppID = [db applicationID];
uint32_t rAppID = [self.db applicationID];

XCTAssertEqual(rAppID, appID);

[db setApplicationIDString:@"acrn"];
[self.db setApplicationIDString:@"acrn"];

NSString *s = [db applicationIDString];
NSString *s = [self.db applicationIDString];

XCTAssertEqualObjects(s, @"acrn");
}
#endif

- (void)testBulkSQL
{
BOOL success;

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);"
"create table bulktest2 (id integer primary key autoincrement, y text);"
"create table bulktest3 (id integer primary key autoincrement, z text);"
"insert into bulktest1 (x) values ('XXX');"
"insert into bulktest2 (y) values ('YYY');"
"insert into bulktest3 (z) values ('ZZZ');";

success = [self.db executeBulkSQL:sql];

XCTAssertTrue(success, @"bulk create");

sql = @"select count(*) as count from bulktest1;"
"select count(*) as count from bulktest2;"
"select count(*) as count from bulktest3;";

success = [self.db executeBulkSQL:sql block:^int(NSDictionary *dictionary) {
NSInteger count = [dictionary[@"count"] integerValue];
XCTAssertEqual(count, 1, @"expected one record for dictionary %@", dictionary);
return 0;
}];

XCTAssertTrue(success, @"bulk select");

sql = @"drop table bulktest1;"
"drop table bulktest2;"
"drop table bulktest3;";

success = [self.db executeBulkSQL:sql];

XCTAssertTrue(success, @"bulk drop");
}

@end
110 changes: 90 additions & 20 deletions src/fmdb/FMDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
#define instancetype id
#endif


typedef int(^FMDBExecuteBulkSQLCallbackBlock)(NSDictionary *resultsDictionary);


/** A SQLite ([http://sqlite.org/](http://sqlite.org/)) Objective-C wrapper.
### Usage
Expand Down Expand Up @@ -241,9 +245,11 @@
/// @name Perform updates
///----------------------

/** Execute update statement
/** Execute single update statement
This method employs [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) for any optional value parameters. This properly escapes any characters that need escape sequences (e.g. quotation marks), which eliminates simple SQL errors as well as protects against SQL injection attacks. This method natively handles `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects. All other object types will be interpreted as text values using the object's `description` method.
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), [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) to bind values to `?` placeholders in the SQL with the optional list of parameters, and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update.
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.
Expand All @@ -261,9 +267,11 @@

- (BOOL)update:(NSString*)sql withErrorAndBindings:(NSError**)outErr, ...;

/** Execute update statement
/** Execute single update statement
This method employs [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) for any optional value parameters. This properly escapes any characters that need escape sequences (e.g. quotation marks), which eliminates simple SQL errors as well as protects against SQL injection attacks. This method natively handles `NSString`, `NSNumber`, `NSNull`, `NSDate`, and `NSData` objects. All other object types will be interpreted as text values using the object's `description` method.
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), [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html) to bind values to `?` placeholders in the SQL with the optional list of parameters, and [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update.
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.
Expand All @@ -275,14 +283,16 @@
@see lastErrorCode
@see lastErrorMessage
@see [`sqlite3_bind`](http://sqlite.org/c3ref/bind_blob.html)
@note This technique supports the use of `?` placeholders in the SQL, automatically binding any supplied value parameters to those placeholders. This approach is more robust than techniques that entail using `stringWithFormat` to manually build SQL statements, which can be problematic if the values happened to include any characters that needed to be quoted.
*/

- (BOOL)executeUpdate:(NSString*)sql, ...;

/** Execute update statement
/** 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 [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL. Do not use `?` placeholders in the SQL if you use this method.
Any sort of SQL statement which is not a `SELECT` statement qualifies as an update. This includes `CREATE`, `UPDATE`, `INSERT`, `ALTER`, `COMMIT`, `BEGIN`, `DETACH`, `DELETE`, `DROP`, `END`, `EXPLAIN`, `VACUUM`, and `REPLACE` statements (plus many more). Basically, if your SQL statement does not begin with `SELECT`, it is an update statement.
@param format The SQL to be performed, with `printf`-style escape sequences.
@param ... Optional parameters to bind to use in conjunction with the `printf`-style escape sequences in the SQL statement.
Expand All @@ -299,9 +309,11 @@

- (BOOL)executeUpdateWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1,2);

/** Execute update statement
/** 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.
Any sort of SQL statement which is not a `SELECT` statement qualifies as an update. This includes `CREATE`, `UPDATE`, `INSERT`, `ALTER`, `COMMIT`, `BEGIN`, `DETACH`, `DELETE`, `DROP`, `END`, `EXPLAIN`, `VACUUM`, and `REPLACE` statements (plus many more). Basically, if your SQL statement does not begin with `SELECT`, it is an update statement.
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.
Expand All @@ -316,9 +328,11 @@

- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments;

/** Execute update statement
/** 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 [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL.
Any sort of SQL statement which is not a `SELECT` statement qualifies as an update. This includes `CREATE`, `UPDATE`, `INSERT`, `ALTER`, `COMMIT`, `BEGIN`, `DETACH`, `DELETE`, `DROP`, `END`, `EXPLAIN`, `VACUUM`, and `REPLACE` statements (plus many more). Basically, if your SQL statement does not begin with `SELECT`, it is an update statement.
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.
Expand All @@ -334,17 +348,69 @@
- (BOOL)executeUpdate:(NSString*)sql withParameterDictionary:(NSDictionary *)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 [`sqlite_step`](http://sqlite.org/c3ref/step.html) to perform the update. Unlike the other `executeUpdate` methods, this uses printf-style formatters (e.g. `%s`, `%d`, etc.) to build the SQL.
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 args A `va_list` of arguments.
@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
*/

// Documentation forthcoming.
- (BOOL)executeUpdate:(NSString*)sql withVAList: (va_list)args;

/** Execute multiple SQL statements
This executes a series of SQL statements that are combined in a single string (e.g. the SQL generated by the `sqlite3` command line `.dump` command). This accepts no value parameters, but rather simply expects a single string with multiple SQL statements, each terminated with a semicolon. This uses `sqlite3_exec`.
@param sql The SQL to be performed
@return `YES` upon success; `NO` upon failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
@see executeBulkSQL:block:
@see [sqlite3_exec()](http://sqlite.org/c3ref/exec.html)
*/

- (BOOL)executeBulkSQL:(NSString *)sql;

/** Execute multiple SQL statements with callback handler
This executes a series of SQL statements that are combined in a single string (e.g. the SQL generated by the `sqlite3` command line `.dump` command). This accepts no value parameters, but rather simply expects a single string with multiple SQL statements, each terminated with a semicolon. This uses `sqlite3_exec`.
@param sql The SQL to be performed.
@param block A block that will be called for any result sets returned by any SQL statements.
Note, if you supply this block, it must return integer value, zero upon success,
non-zero value upon failure (which will stop the bulk execution of the SQL. This block
takes two parameters, the `void *userInfo` and a `NSDictionary *resultsDictionary`.
This may be `nil`.
@return `YES` upon success; `NO` upon failure. If failed, you can call `<lastError>`,
`<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
@see executeBulkSQL:
@see [sqlite3_exec()](http://sqlite.org/c3ref/exec.html)
*/

- (BOOL)executeBulkSQL:(NSString *)sql block:(FMDBExecuteBulkSQLCallbackBlock)block;

/** Last insert rowid
Each entry in an SQLite table has a unique 64-bit signed integer key called the "rowid". The rowid is always available as an undeclared column named `ROWID`, `OID`, or `_ROWID_` as long as those names are not also used by explicitly declared columns. If the table has a column of type `INTEGER PRIMARY KEY` then that column is another alias for the rowid.
This routine returns the rowid of the most recent successful `INSERT` into the database from the database connection in the first argument. As of SQLite version 3.7.7, this routines records the last insert rowid of both ordinary tables and virtual tables. If no successful `INSERT`s have ever occurred on that database connection, zero is returned.
@return The rowid of the last inserted row.
@see [sqlite3_last_insert_rowid()](http://sqlite.org/c3ref/last_insert_rowid.html)
*/
Expand All @@ -355,6 +421,8 @@
This function returns the number of database rows that were changed or inserted or deleted by the most recently completed SQL statement on the database connection specified by the first parameter. Only changes that are directly specified by the INSERT, UPDATE, or DELETE statement are counted.
@return The number of rows changed by prior SQL statement.
@see [sqlite3_changes()](http://sqlite.org/c3ref/changes.html)
*/
Expand Down Expand Up @@ -449,8 +517,6 @@
// Documentation forthcoming.
- (FMResultSet *)executeQuery:(NSString*)sql withVAList: (va_list)args;



///-------------------
/// @name Transactions
///-------------------
Expand Down Expand Up @@ -640,7 +706,7 @@
Returns the English-language text that describes the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined.
@returns `NSString` of the last error message.
@return `NSString` of the last error message.
@see [sqlite3_errmsg()](http://sqlite.org/c3ref/errcode.html)
@see lastErrorCode
Expand All @@ -654,7 +720,7 @@
Returns the numeric result code or extended result code for the most recent failed SQLite API call associated with a database connection. If a prior API call failed but the most recent API call succeeded, this return value is undefined.
@returns Integer value of the last error code.
@return Integer value of the last error code.
@see [sqlite3_errcode()](http://sqlite.org/c3ref/errcode.html)
@see lastErrorMessage
Expand Down Expand Up @@ -746,7 +812,7 @@
@param block Block of code to perform from within save point.
@return `YES` on success; `NO` on failure. If failed, you can call `<lastError>`, `<lastErrorCode>`, or `<lastErrorMessage>` for diagnostic information regarding the failure.
@return The NSError corresponding to the error, if any. If no error, returns `nil`.
@see startSavePointWithName:error:
@see releaseSavePointWithName:error:
Expand All @@ -764,7 +830,7 @@

/** Test to see if the library is threadsafe
@return Zero if and only if SQLite was compiled with mutexing code omitted due to the SQLITE_THREADSAFE compile-time option being set to 0.
@return `NO` if and only if SQLite was compiled with mutexing code omitted due to the SQLITE_THREADSAFE compile-time option being set to 0.
@see [sqlite3_threadsafe()](http://sqlite.org/c3ref/threadsafe.html)
*/
Expand All @@ -773,6 +839,8 @@

/** Run-time library version numbers
@return The sqlite library version string.
@see [sqlite3_libversion()](http://sqlite.org/c3ref/libversion.html)
*/

Expand Down Expand Up @@ -890,7 +958,7 @@
@param s `NSString` to convert to `NSDate`.
@return `nil` if no formatter is set.
@return The `NSDate` object; or `nil` if no formatter is set.
@see hasDateFormatter
@see setDateFormat:
Expand All @@ -905,7 +973,7 @@
@param date `NSDate` of date to convert to `NSString`.
@return `nil` if no formatter is set.
@return The `NSString` representation of the date; `nil` if no formatter is set.
@see hasDateFormatter
@see setDateFormat:
Expand Down Expand Up @@ -956,6 +1024,8 @@

@property (atomic, assign) sqlite3_stmt *statement;

/** Indication of whether the statement is in use */

@property (atomic, assign) BOOL inUse;

///----------------------------
Expand Down
Loading

0 comments on commit 5cd7302

Please sign in to comment.