From 711cc966cba1fc04aa384a053fcdace56967b608 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Sat, 5 Jun 2021 08:55:59 -0500 Subject: [PATCH 1/8] Refactor extensions into separate target --- Package.swift | 16 ++- Sources/CSQLite/csqlite_shims.c | 68 --------- Sources/CSQLite/include/csqlite_shims.h | 60 -------- .../{CSQLite => CSQLiteExtensions}/carray.c | 0 .../CSQLiteExtensions/csqlite_extensions.c | 84 +++++++++++ .../{CSQLite => CSQLiteExtensions}/decimal.c | 0 .../{CSQLite => CSQLiteExtensions}/ieee754.c | 0 .../include/csqlite_extensions.h | 76 ++++++++++ .../{CSQLite => CSQLiteExtensions}/series.c | 0 .../{CSQLite => CSQLiteExtensions}/shathree.c | 0 Sources/{CSQLite => CSQLiteExtensions}/uuid.c | 0 .../CSQLiteExtensionsTests.swift | 133 ++++++++++++++++++ Tests/CSQLiteTests/CSQLiteTests.swift | 122 ---------------- 13 files changed, 305 insertions(+), 254 deletions(-) rename Sources/{CSQLite => CSQLiteExtensions}/carray.c (100%) create mode 100644 Sources/CSQLiteExtensions/csqlite_extensions.c rename Sources/{CSQLite => CSQLiteExtensions}/decimal.c (100%) rename Sources/{CSQLite => CSQLiteExtensions}/ieee754.c (100%) create mode 100644 Sources/CSQLiteExtensions/include/csqlite_extensions.h rename Sources/{CSQLite => CSQLiteExtensions}/series.c (100%) rename Sources/{CSQLite => CSQLiteExtensions}/shathree.c (100%) rename Sources/{CSQLite => CSQLiteExtensions}/uuid.c (100%) create mode 100644 Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift diff --git a/Package.swift b/Package.swift index a82780f..03c54a1 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( // Products define the executables and libraries a package produces, and make them visible to other packages. .library( name: "CSQLite", - targets: ["CSQLite"]), + targets: ["CSQLite", "CSQLiteExtensions"]), ], dependencies: [ // Dependencies declare other packages that this package depends on. @@ -59,14 +59,22 @@ let package = Package( .define("SQLITE_ENABLE_RTREE", to: "1"), // .define("SQLITE_ENABLE_SESSION", to: "1"), .define("SQLITE_ENABLE_SNAPSHOT", to: "1"), - .define("SQLITE_ENABLE_STAT4", to: "1"), - .define("SQLITE_CORE", to: "1")], + .define("SQLITE_ENABLE_STAT4", to: "1")], linkerSettings: [ .linkedLibrary("m") ]), + .target( + name: "CSQLiteExtensions", + dependencies: [ .target(name: "CSQLite") ], + cSettings: [ + .define("SQLITE_CORE", to: "1"), + ]), .testTarget( name: "CSQLiteTests", - dependencies: ["CSQLite"]) + dependencies: ["CSQLite"]), + .testTarget( + name: "CSQLiteExtensionsTests", + dependencies: ["CSQLiteExtensions"]) ], cLanguageStandard: .gnu11 ) diff --git a/Sources/CSQLite/csqlite_shims.c b/Sources/CSQLite/csqlite_shims.c index 365fdc0..8717091 100644 --- a/Sources/CSQLite/csqlite_shims.c +++ b/Sources/CSQLite/csqlite_shims.c @@ -245,71 +245,3 @@ int csqlite_sqlite3_vtab_config_directonly(sqlite3 *db) { return sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); } - -// MARK: - Database extensions - -void sqlite3_carray_init(); -int csqlite_sqlite3_auto_extension_carray() -{ - return sqlite3_auto_extension(sqlite3_carray_init); -} - -int csqlite_sqlite3_cancel_auto_extension_carray() -{ - return sqlite3_cancel_auto_extension(sqlite3_carray_init); -} - -void sqlite3_decimal_init(); -int csqlite_sqlite3_auto_extension_decimal() -{ - return sqlite3_auto_extension(sqlite3_decimal_init); -} - -int csqlite_sqlite3_cancel_auto_extension_decimal() -{ - return sqlite3_cancel_auto_extension(sqlite3_decimal_init); -} - -void sqlite3_ieee_init(); -int csqlite_sqlite3_auto_extension_ieee754() -{ - return sqlite3_auto_extension(sqlite3_ieee_init); -} - -int csqlite_sqlite3_cancel_auto_extension_ieee754() -{ - return sqlite3_cancel_auto_extension(sqlite3_ieee_init); -} - -void sqlite3_series_init(); -int csqlite_sqlite3_auto_extension_series() -{ - return sqlite3_auto_extension(sqlite3_series_init); -} - -int csqlite_sqlite3_cancel_auto_extension_series() -{ - return sqlite3_cancel_auto_extension(sqlite3_series_init); -} - -void sqlite3_shathree_init(); -int csqlite_sqlite3_auto_extension_sha3() -{ - return sqlite3_auto_extension(sqlite3_shathree_init); -} - -int csqlite_sqlite3_cancel_auto_extension_sha3() -{ - return sqlite3_cancel_auto_extension(sqlite3_shathree_init); -} - -void sqlite3_uuid_init(); -int csqlite_sqlite3_auto_extension_uuid() -{ - return sqlite3_auto_extension(sqlite3_uuid_init); -} - -int csqlite_sqlite3_cancel_auto_extension_uuid() -{ - return sqlite3_cancel_auto_extension(sqlite3_uuid_init); -} diff --git a/Sources/CSQLite/include/csqlite_shims.h b/Sources/CSQLite/include/csqlite_shims.h index 9ee8bdc..483cb3b 100644 --- a/Sources/CSQLite/include/csqlite_shims.h +++ b/Sources/CSQLite/include/csqlite_shims.h @@ -117,63 +117,3 @@ int csqlite_sqlite3_vtab_config_constraint_support(sqlite3 *db, int x); int csqlite_sqlite3_vtab_config_innocuous(sqlite3 *db); /// Equivalent to `sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY)` int csqlite_sqlite3_vtab_config_directonly(sqlite3 *db); - -// MARK: - Database extensions -// See https://sqlite.org/loadext.html - -// The Carray() Table-Valued Function -// See https://sqlite.org/carray.html - -/* - ** Interface definitions for the CARRAY table-valued function - ** extension. - */ - -/* Use this interface to bind an array to the single-argument version - ** of CARRAY(). - */ -int sqlite3_carray_bind( - sqlite3_stmt *pStmt, /* Statement to be bound */ - int i, /* Parameter index */ - void *aData, /* Pointer to array data */ - int nData, /* Number of data elements */ - int mFlags, /* CARRAY flags */ - void (*xDel)(void*) /* Destructor for aData*/ -); - -/* Allowed values for the mFlags parameter to sqlite3_carray_bind(). - */ -#define CARRAY_INT32 0 /* Data is 32-bit signed integers */ -#define CARRAY_INT64 1 /* Data is 64-bit signed integers */ -#define CARRAY_DOUBLE 2 /* Data is doubles */ -#define CARRAY_TEXT 3 /* Data is char* */ - -/// Equivalent to `sqlite3_auto_extension(sqlite3_carray_init)` -int csqlite_sqlite3_auto_extension_carray(); -/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_carray_init)` -int csqlite_sqlite3_cancel_auto_extension_carray(); - -/// Equivalent to `sqlite3_auto_extension(sqlite3_decimal_init)` -int csqlite_sqlite3_auto_extension_decimal(); -/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_decimal_init)` -int csqlite_sqlite3_cancel_auto_extension_decimal(); - -/// Equivalent to `sqlite3_auto_extension(sqlite3_ieee_init)` -int csqlite_sqlite3_auto_extension_ieee754(); -/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_ieee_init)` -int csqlite_sqlite3_cancel_auto_extension_ieee754(); - -/// Equivalent to `sqlite3_auto_extension(sqlite3_series_init)` -int csqlite_sqlite3_auto_extension_series(); -/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_series_init)` -int csqlite_sqlite3_cancel_auto_extension_series(); - -/// Equivalent to `sqlite3_auto_extension(sqlite3_shathree_init)` -int csqlite_sqlite3_auto_extension_sha3(); -/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_shathree_init)` -int csqlite_sqlite3_cancel_auto_extension_sha3(); - -/// Equivalent to `sqlite3_auto_extension(sqlite3_uuid_init)` -int csqlite_sqlite3_auto_extension_uuid(); -/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_uuid_init)` -int csqlite_sqlite3_cancel_auto_extension_uuid(); diff --git a/Sources/CSQLite/carray.c b/Sources/CSQLiteExtensions/carray.c similarity index 100% rename from Sources/CSQLite/carray.c rename to Sources/CSQLiteExtensions/carray.c diff --git a/Sources/CSQLiteExtensions/csqlite_extensions.c b/Sources/CSQLiteExtensions/csqlite_extensions.c new file mode 100644 index 0000000..c5f5158 --- /dev/null +++ b/Sources/CSQLiteExtensions/csqlite_extensions.c @@ -0,0 +1,84 @@ +/* + ** 2021-06-04 + ** + ** The author disclaims copyright to this source code. In place of + ** a legal notice, here is a blessing: + ** + ** May you do good and not evil. + ** May you find forgiveness for yourself and forgive others. + ** May you share freely, never taking more than you give. + ** + ****************************************************************************** + ** + ** Wrappers for C functions not easily accessible from Swift. + */ + +#include "csqlite_extensions.h" + +// MARK: - Database extensions + +void sqlite3_carray_init(); +int csqlite_sqlite3_auto_extension_carray() +{ + return sqlite3_auto_extension(sqlite3_carray_init); +} + +int csqlite_sqlite3_cancel_auto_extension_carray() +{ + return sqlite3_cancel_auto_extension(sqlite3_carray_init); +} + +void sqlite3_decimal_init(); +int csqlite_sqlite3_auto_extension_decimal() +{ + return sqlite3_auto_extension(sqlite3_decimal_init); +} + +int csqlite_sqlite3_cancel_auto_extension_decimal() +{ + return sqlite3_cancel_auto_extension(sqlite3_decimal_init); +} + +void sqlite3_ieee_init(); +int csqlite_sqlite3_auto_extension_ieee754() +{ + return sqlite3_auto_extension(sqlite3_ieee_init); +} + +int csqlite_sqlite3_cancel_auto_extension_ieee754() +{ + return sqlite3_cancel_auto_extension(sqlite3_ieee_init); +} + +void sqlite3_series_init(); +int csqlite_sqlite3_auto_extension_series() +{ + return sqlite3_auto_extension(sqlite3_series_init); +} + +int csqlite_sqlite3_cancel_auto_extension_series() +{ + return sqlite3_cancel_auto_extension(sqlite3_series_init); +} + +void sqlite3_shathree_init(); +int csqlite_sqlite3_auto_extension_sha3() +{ + return sqlite3_auto_extension(sqlite3_shathree_init); +} + +int csqlite_sqlite3_cancel_auto_extension_sha3() +{ + return sqlite3_cancel_auto_extension(sqlite3_shathree_init); +} + +void sqlite3_uuid_init(); +int csqlite_sqlite3_auto_extension_uuid() +{ + return sqlite3_auto_extension(sqlite3_uuid_init); +} + +int csqlite_sqlite3_cancel_auto_extension_uuid() +{ + return sqlite3_cancel_auto_extension(sqlite3_uuid_init); +} diff --git a/Sources/CSQLite/decimal.c b/Sources/CSQLiteExtensions/decimal.c similarity index 100% rename from Sources/CSQLite/decimal.c rename to Sources/CSQLiteExtensions/decimal.c diff --git a/Sources/CSQLite/ieee754.c b/Sources/CSQLiteExtensions/ieee754.c similarity index 100% rename from Sources/CSQLite/ieee754.c rename to Sources/CSQLiteExtensions/ieee754.c diff --git a/Sources/CSQLiteExtensions/include/csqlite_extensions.h b/Sources/CSQLiteExtensions/include/csqlite_extensions.h new file mode 100644 index 0000000..a0895be --- /dev/null +++ b/Sources/CSQLiteExtensions/include/csqlite_extensions.h @@ -0,0 +1,76 @@ +/* + ** 2021-06-04 + ** + ** The author disclaims copyright to this source code. In place of + ** a legal notice, here is a blessing: + ** + ** May you do good and not evil. + ** May you find forgiveness for yourself and forgive others. + ** May you share freely, never taking more than you give. + ** + ****************************************************************************** + ** + ** Wrappers for C functions not easily accessible from Swift. + */ + +#include "sqlite3.h" + +// MARK: - Database extensions +// See https://sqlite.org/loadext.html + +// The Carray() Table-Valued Function +// See https://sqlite.org/carray.html + +/* + ** Interface definitions for the CARRAY table-valued function + ** extension. + */ + +/* Use this interface to bind an array to the single-argument version + ** of CARRAY(). + */ +int sqlite3_carray_bind( + sqlite3_stmt *pStmt, /* Statement to be bound */ + int i, /* Parameter index */ + void *aData, /* Pointer to array data */ + int nData, /* Number of data elements */ + int mFlags, /* CARRAY flags */ + void (*xDel)(void*) /* Destructor for aData*/ +); + +/* Allowed values for the mFlags parameter to sqlite3_carray_bind(). + */ +#define CARRAY_INT32 0 /* Data is 32-bit signed integers */ +#define CARRAY_INT64 1 /* Data is 64-bit signed integers */ +#define CARRAY_DOUBLE 2 /* Data is doubles */ +#define CARRAY_TEXT 3 /* Data is char* */ + +/// Equivalent to `sqlite3_auto_extension(sqlite3_carray_init)` +int csqlite_sqlite3_auto_extension_carray(); +/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_carray_init)` +int csqlite_sqlite3_cancel_auto_extension_carray(); + +/// Equivalent to `sqlite3_auto_extension(sqlite3_decimal_init)` +int csqlite_sqlite3_auto_extension_decimal(); +/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_decimal_init)` +int csqlite_sqlite3_cancel_auto_extension_decimal(); + +/// Equivalent to `sqlite3_auto_extension(sqlite3_ieee_init)` +int csqlite_sqlite3_auto_extension_ieee754(); +/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_ieee_init)` +int csqlite_sqlite3_cancel_auto_extension_ieee754(); + +/// Equivalent to `sqlite3_auto_extension(sqlite3_series_init)` +int csqlite_sqlite3_auto_extension_series(); +/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_series_init)` +int csqlite_sqlite3_cancel_auto_extension_series(); + +/// Equivalent to `sqlite3_auto_extension(sqlite3_shathree_init)` +int csqlite_sqlite3_auto_extension_sha3(); +/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_shathree_init)` +int csqlite_sqlite3_cancel_auto_extension_sha3(); + +/// Equivalent to `sqlite3_auto_extension(sqlite3_uuid_init)` +int csqlite_sqlite3_auto_extension_uuid(); +/// Equivalent to `sqlite3_cancel_auto_extension(sqlite3_uuid_init)` +int csqlite_sqlite3_cancel_auto_extension_uuid(); diff --git a/Sources/CSQLite/series.c b/Sources/CSQLiteExtensions/series.c similarity index 100% rename from Sources/CSQLite/series.c rename to Sources/CSQLiteExtensions/series.c diff --git a/Sources/CSQLite/shathree.c b/Sources/CSQLiteExtensions/shathree.c similarity index 100% rename from Sources/CSQLite/shathree.c rename to Sources/CSQLiteExtensions/shathree.c diff --git a/Sources/CSQLite/uuid.c b/Sources/CSQLiteExtensions/uuid.c similarity index 100% rename from Sources/CSQLite/uuid.c rename to Sources/CSQLiteExtensions/uuid.c diff --git a/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift b/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift new file mode 100644 index 0000000..b40c60e --- /dev/null +++ b/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift @@ -0,0 +1,133 @@ +import XCTest +@testable import CSQLite +@testable import CSQLiteExtensions + +final class CSQLiteTests: XCTestCase { + override class func setUp() { + super.setUp() + // It's necessary to call sqlite3_initialize() since SQLITE_OMIT_AUTOINIT is defined + XCTAssert(sqlite3_initialize() == SQLITE_OK) + } + + func testCarray() { + XCTAssert(csqlite_sqlite3_auto_extension_carray() == SQLITE_OK) + + var db: OpaquePointer? + XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) + + XCTAssert(sqlite3_exec(db, "create table t1(a);", nil, nil, nil) == SQLITE_OK) + XCTAssert(sqlite3_exec(db, "insert into t1(a) values (2),(3),(4),(5);", nil, nil, nil) == SQLITE_OK) + + var stmt: OpaquePointer? + XCTAssert(sqlite3_prepare_v2(db, "select a from t1 where a in carray(?);", -1, &stmt, nil) == SQLITE_OK) + let array: [Int32] = [3,5]; + let mem = UnsafeMutableBufferPointer.allocate(capacity: array.count) + _ = mem.initialize(from: array) + XCTAssert(sqlite3_carray_bind(stmt, 1, mem.baseAddress, Int32(array.count), CARRAY_INT32, { + $0?.deallocate() + }) == SQLITE_OK) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + var i = sqlite3_column_int(stmt, 0) + XCTAssertEqual(i, 3) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + i = sqlite3_column_int(stmt, 0) + XCTAssertEqual(i, 5) + + XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) + XCTAssert(sqlite3_close(db) == SQLITE_OK) + } + + func testDecimal() { + XCTAssert(csqlite_sqlite3_auto_extension_decimal() == SQLITE_OK) + + var db: OpaquePointer? + XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) + + var stmt: OpaquePointer? + XCTAssert(sqlite3_prepare_v2(db, "select decimal_add('1.67','2.33');", -1, &stmt, nil) == SQLITE_OK) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + let r = String(cString: sqlite3_column_text(stmt, 0)) + XCTAssertEqual(r, "4.00") + + XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) + XCTAssert(sqlite3_close(db) == SQLITE_OK) + } + + func testIEEE() { + XCTAssert(csqlite_sqlite3_auto_extension_ieee754() == SQLITE_OK) + + var db: OpaquePointer? + XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) + + var stmt: OpaquePointer? + XCTAssert(sqlite3_prepare_v2(db, "select ieee754(45.25);", -1, &stmt, nil) == SQLITE_OK) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + let f = String(cString: sqlite3_column_text(stmt, 0)) + XCTAssertEqual(f, "ieee754(181,-2)") + + XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) + XCTAssert(sqlite3_close(db) == SQLITE_OK) + } + + func testSeries() { + XCTAssert(csqlite_sqlite3_auto_extension_series() == SQLITE_OK) + + var db: OpaquePointer? + XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) + + var stmt: OpaquePointer? + XCTAssert(sqlite3_prepare_v2(db, "select * from generate_series(10,20,5);", -1, &stmt, nil) == SQLITE_OK) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + var i = sqlite3_column_int(stmt, 0) + XCTAssertEqual(i, 10) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + i = sqlite3_column_int(stmt, 0) + XCTAssertEqual(i, 15) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + i = sqlite3_column_int(stmt, 0) + XCTAssertEqual(i, 20) + + XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) + XCTAssert(sqlite3_close(db) == SQLITE_OK) + } + + func testSHA3() { + XCTAssert(csqlite_sqlite3_auto_extension_sha3() == SQLITE_OK) + + var db: OpaquePointer? + XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) + + var stmt: OpaquePointer? + XCTAssert(sqlite3_prepare_v2(db, "select lower(hex(sha3('sqlite')));", -1, &stmt, nil) == SQLITE_OK) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + let h = String(cString: sqlite3_column_text(stmt, 0)) + XCTAssertEqual(h, "963a88636d4c9cc3f011dfc9dc0058e96669d80a89893c68c0bb08a6a8208db3") + + XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) + XCTAssert(sqlite3_close(db) == SQLITE_OK) + } + + func testUUID() { + XCTAssert(csqlite_sqlite3_auto_extension_uuid() == SQLITE_OK) + + var db: OpaquePointer? + XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) + + var stmt: OpaquePointer? + XCTAssert(sqlite3_prepare_v2(db, "select uuid();", -1, &stmt, nil) == SQLITE_OK) + XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) + let u = String(cString: sqlite3_column_text(stmt, 0)) + let comps = u.components(separatedBy: "-") + XCTAssertEqual(comps.count, 5) + XCTAssertEqual(comps[0].count, 8) + XCTAssertEqual(comps[1].count, 4) + XCTAssertEqual(comps[2].count, 4) + XCTAssertEqual(comps[3].count, 4) + XCTAssertEqual(comps[4].count, 12) + let uu = UUID(uuidString: u) + XCTAssertNotNil(uu) + + XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) + XCTAssert(sqlite3_close(db) == SQLITE_OK) + } +} diff --git a/Tests/CSQLiteTests/CSQLiteTests.swift b/Tests/CSQLiteTests/CSQLiteTests.swift index bdfce98..8c62f6d 100644 --- a/Tests/CSQLiteTests/CSQLiteTests.swift +++ b/Tests/CSQLiteTests/CSQLiteTests.swift @@ -62,126 +62,4 @@ final class CSQLiteTests: XCTestCase { XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) XCTAssert(sqlite3_close(db) == SQLITE_OK) } - - func testCarray() { - XCTAssert(csqlite_sqlite3_auto_extension_carray() == SQLITE_OK) - - var db: OpaquePointer? - XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) - - XCTAssert(sqlite3_exec(db, "create table t1(a);", nil, nil, nil) == SQLITE_OK) - XCTAssert(sqlite3_exec(db, "insert into t1(a) values (2),(3),(4),(5);", nil, nil, nil) == SQLITE_OK) - - var stmt: OpaquePointer? - XCTAssert(sqlite3_prepare_v2(db, "select a from t1 where a in carray(?);", -1, &stmt, nil) == SQLITE_OK) - let array: [Int32] = [3,5]; - let mem = UnsafeMutableBufferPointer.allocate(capacity: array.count) - _ = mem.initialize(from: array) - XCTAssert(sqlite3_carray_bind(stmt, 1, mem.baseAddress, Int32(array.count), CARRAY_INT32, { - $0?.deallocate() - }) == SQLITE_OK) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - var i = sqlite3_column_int(stmt, 0) - XCTAssertEqual(i, 3) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - i = sqlite3_column_int(stmt, 0) - XCTAssertEqual(i, 5) - - XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) - XCTAssert(sqlite3_close(db) == SQLITE_OK) - } - - func testDecimal() { - XCTAssert(csqlite_sqlite3_auto_extension_decimal() == SQLITE_OK) - - var db: OpaquePointer? - XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) - - var stmt: OpaquePointer? - XCTAssert(sqlite3_prepare_v2(db, "select decimal_add('1.67','2.33');", -1, &stmt, nil) == SQLITE_OK) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - let r = String(cString: sqlite3_column_text(stmt, 0)) - XCTAssertEqual(r, "4.00") - - XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) - XCTAssert(sqlite3_close(db) == SQLITE_OK) - } - - func testIEEE() { - XCTAssert(csqlite_sqlite3_auto_extension_ieee754() == SQLITE_OK) - - var db: OpaquePointer? - XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) - - var stmt: OpaquePointer? - XCTAssert(sqlite3_prepare_v2(db, "select ieee754(45.25);", -1, &stmt, nil) == SQLITE_OK) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - let f = String(cString: sqlite3_column_text(stmt, 0)) - XCTAssertEqual(f, "ieee754(181,-2)") - - XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) - XCTAssert(sqlite3_close(db) == SQLITE_OK) - } - - func testSeries() { - XCTAssert(csqlite_sqlite3_auto_extension_series() == SQLITE_OK) - - var db: OpaquePointer? - XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) - - var stmt: OpaquePointer? - XCTAssert(sqlite3_prepare_v2(db, "select * from generate_series(10,20,5);", -1, &stmt, nil) == SQLITE_OK) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - var i = sqlite3_column_int(stmt, 0) - XCTAssertEqual(i, 10) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - i = sqlite3_column_int(stmt, 0) - XCTAssertEqual(i, 15) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - i = sqlite3_column_int(stmt, 0) - XCTAssertEqual(i, 20) - - XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) - XCTAssert(sqlite3_close(db) == SQLITE_OK) - } - - func testSHA3() { - XCTAssert(csqlite_sqlite3_auto_extension_sha3() == SQLITE_OK) - - var db: OpaquePointer? - XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) - - var stmt: OpaquePointer? - XCTAssert(sqlite3_prepare_v2(db, "select lower(hex(sha3('sqlite')));", -1, &stmt, nil) == SQLITE_OK) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - let h = String(cString: sqlite3_column_text(stmt, 0)) - XCTAssertEqual(h, "963a88636d4c9cc3f011dfc9dc0058e96669d80a89893c68c0bb08a6a8208db3") - - XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) - XCTAssert(sqlite3_close(db) == SQLITE_OK) - } - - func testUUID() { - XCTAssert(csqlite_sqlite3_auto_extension_uuid() == SQLITE_OK) - - var db: OpaquePointer? - XCTAssert(sqlite3_open_v2(":memory:", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nil) == SQLITE_OK) - - var stmt: OpaquePointer? - XCTAssert(sqlite3_prepare_v2(db, "select uuid();", -1, &stmt, nil) == SQLITE_OK) - XCTAssert(sqlite3_step(stmt) == SQLITE_ROW) - let u = String(cString: sqlite3_column_text(stmt, 0)) - let comps = u.components(separatedBy: "-") - XCTAssertEqual(comps.count, 5) - XCTAssertEqual(comps[0].count, 8) - XCTAssertEqual(comps[1].count, 4) - XCTAssertEqual(comps[2].count, 4) - XCTAssertEqual(comps[3].count, 4) - XCTAssertEqual(comps[4].count, 12) - let uu = UUID(uuidString: u) - XCTAssertNotNil(uu) - - XCTAssert(sqlite3_finalize(stmt) == SQLITE_OK) - XCTAssert(sqlite3_close(db) == SQLITE_OK) - } } From 3e49f1d06ee8204e33de23478c2be6073b557f19 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Fri, 24 May 2024 07:11:09 -0500 Subject: [PATCH 2/8] Rename class and add header --- .../CSQLiteExtensionsTests.swift | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift b/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift index b40c60e..2bc2a80 100644 --- a/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift +++ b/Tests/CSQLiteExtensionsTests/CSQLiteExtensionsTests.swift @@ -1,8 +1,22 @@ +/* + ** 2024-05-24 + ** + ** The author disclaims copyright to this source code. In place of + ** a legal notice, here is a blessing: + ** + ** May you do good and not evil. + ** May you find forgiveness for yourself and forgive others. + ** May you share freely, never taking more than you give. + ** + ****************************************************************************** + ** + ** Basic tests of CSQLiteExtensions functionality. + */ + import XCTest -@testable import CSQLite @testable import CSQLiteExtensions -final class CSQLiteTests: XCTestCase { +final class CSQLiteExtensionsTests: XCTestCase { override class func setUp() { super.setUp() // It's necessary to call sqlite3_initialize() since SQLITE_OMIT_AUTOINIT is defined From bd61218c220fc063496e2e41afd3388fd2442cf4 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Fri, 24 May 2024 07:14:52 -0500 Subject: [PATCH 3/8] Update header comment --- Sources/CSQLiteExtensions/csqlite_extensions.c | 2 +- Sources/CSQLiteExtensions/include/csqlite_extensions.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/CSQLiteExtensions/csqlite_extensions.c b/Sources/CSQLiteExtensions/csqlite_extensions.c index 267429c..f86c66f 100644 --- a/Sources/CSQLiteExtensions/csqlite_extensions.c +++ b/Sources/CSQLiteExtensions/csqlite_extensions.c @@ -10,7 +10,7 @@ ** ****************************************************************************** ** - ** Wrappers for C functions not easily accessible from Swift. + ** Functions to manage automatic database extension registration from Swift. */ #include "csqlite_extensions.h" diff --git a/Sources/CSQLiteExtensions/include/csqlite_extensions.h b/Sources/CSQLiteExtensions/include/csqlite_extensions.h index 35c8248..3e3bce6 100644 --- a/Sources/CSQLiteExtensions/include/csqlite_extensions.h +++ b/Sources/CSQLiteExtensions/include/csqlite_extensions.h @@ -10,7 +10,7 @@ ** ****************************************************************************** ** - ** Wrappers for C functions not easily accessible from Swift. + ** Functions to manage automatic database extension registration from Swift. */ // MARK: - Database extensions From 63e8a0a18a9b06c999ec8ccf81143d907e306689 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Sun, 2 Jun 2024 12:00:44 -0500 Subject: [PATCH 4/8] Update module maps --- Sources/CSQLite/include/module.modulemap | 1 - Sources/CSQLiteExtensions/include/module.modulemap | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 Sources/CSQLiteExtensions/include/module.modulemap diff --git a/Sources/CSQLite/include/module.modulemap b/Sources/CSQLite/include/module.modulemap index a569ebe..d64a094 100644 --- a/Sources/CSQLite/include/module.modulemap +++ b/Sources/CSQLite/include/module.modulemap @@ -1,7 +1,6 @@ module CSQLite { header "sqlite3.h" header "sqlite3ext.h" - header "carray.h" header "csqlite_shims.h" export * } diff --git a/Sources/CSQLiteExtensions/include/module.modulemap b/Sources/CSQLiteExtensions/include/module.modulemap new file mode 100644 index 0000000..4101667 --- /dev/null +++ b/Sources/CSQLiteExtensions/include/module.modulemap @@ -0,0 +1,5 @@ +module CSQLiteExtensions { + header "csqlite_extensions.h" + header "carray.h" + export * +} From 9afebf0160400b0dfd112bde6599a6e43b5a0942 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Thu, 24 Oct 2024 10:01:33 -0500 Subject: [PATCH 5/8] Move percentile.c --- Sources/{CSQLite => CSQLiteExtensions}/percentile.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Sources/{CSQLite => CSQLiteExtensions}/percentile.c (100%) diff --git a/Sources/CSQLite/percentile.c b/Sources/CSQLiteExtensions/percentile.c similarity index 100% rename from Sources/CSQLite/percentile.c rename to Sources/CSQLiteExtensions/percentile.c From 1d12543a4a0ab053b0ab1a29b14cadde85dc16a3 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Thu, 24 Oct 2024 10:06:53 -0500 Subject: [PATCH 6/8] Move SQLITE_CORE define --- Package.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 8969d3a..628e9d2 100644 --- a/Package.swift +++ b/Package.swift @@ -74,9 +74,6 @@ let package = Package( .define("SQLITE_ENABLE_SNAPSHOT"), .define("SQLITE_ENABLE_STMTVTAB"), .define("SQLITE_ENABLE_STAT4"), - // For statically linking extensions - // https://sqlite.org/loadext.html#statically_linking_a_run_time_loadable_extension - .define("SQLITE_CORE", to: "1"), ], linkerSettings: [ .linkedLibrary("m"), @@ -87,6 +84,8 @@ let package = Package( "CSQLite", ], cSettings: [ + // For statically linking extensions + // https://sqlite.org/loadext.html#statically_linking_a_run_time_loadable_extension .define("SQLITE_CORE", to: "1"), ]), .testTarget( From e7927b8fa5318180c6cadbffab2dda840edba6f1 Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Wed, 28 May 2025 13:17:28 -0500 Subject: [PATCH 7/8] Update Swift 5.3 package --- Package.swift | 2 +- Package@swift-5.3.swift | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Package.swift b/Package.swift index 2b11aca..65663f3 100644 --- a/Package.swift +++ b/Package.swift @@ -270,7 +270,7 @@ let package = Package( name: "CSQLiteExtensionsTests", dependencies: [ "CSQLiteExtensions", - ]) + ]), ], cLanguageStandard: .gnu11 ) diff --git a/Package@swift-5.3.swift b/Package@swift-5.3.swift index eacc02b..ce159f0 100644 --- a/Package@swift-5.3.swift +++ b/Package@swift-5.3.swift @@ -92,6 +92,7 @@ let package = Package( name: "CSQLite", targets: [ "CSQLite", + "CSQLiteExtensions", ]), ], targets: [ @@ -99,19 +100,30 @@ let package = Package( // Targets can depend on other targets in this package and products from dependencies. .target( name: "CSQLite", - cSettings: compileTimeOptions + platformConfiguration + features + [ + cSettings: compileTimeOptions + platformConfiguration + features, + linkerSettings: [ + .linkedLibrary("m"), + ]), + .target( + name: "CSQLiteExtensions", + dependencies: [ + "CSQLite", + ], + cSettings: [ // For statically linking extensions // https://sqlite.org/loadext.html#statically_linking_a_run_time_loadable_extension .define("SQLITE_CORE", to: "1"), - ], - linkerSettings: [ - .linkedLibrary("m"), ]), .testTarget( name: "CSQLiteTests", dependencies: [ "CSQLite", - ]) + ]), + .testTarget( + name: "CSQLiteExtensionsTests", + dependencies: [ + "CSQLiteExtensions", + ]), ], cLanguageStandard: .gnu11 ) From aa69fafb95f244bdd1723d393f5bf2add20f806c Mon Sep 17 00:00:00 2001 From: "Stephen F. Booth" Date: Thu, 29 May 2025 08:14:46 -0500 Subject: [PATCH 8/8] Reorder `header` --- Sources/CSQLiteExtensions/include/module.modulemap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CSQLiteExtensions/include/module.modulemap b/Sources/CSQLiteExtensions/include/module.modulemap index 4101667..d44bd73 100644 --- a/Sources/CSQLiteExtensions/include/module.modulemap +++ b/Sources/CSQLiteExtensions/include/module.modulemap @@ -1,5 +1,5 @@ module CSQLiteExtensions { - header "csqlite_extensions.h" header "carray.h" + header "csqlite_extensions.h" export * }